有几个容易错的地方提醒大家:
1.主公和忠臣决斗忠臣不能出杀
2.有可能某一次出的牌影响到跳反/跳忠,之前本来不能出的现在可以出了,要重新判一下。(例如某只反猪出了个南蛮入侵,他的下一位为主猪出了无懈可击,跳忠了,之前这只猪手牌有一张杀在南蛮入侵之前,但因为没有目标被跳过了,现在要重新用)
最后给一份带调试的代码供大家使用(题解区第三页 Ice_teapoy 大佬的调试也很详细,大家也可以看看他的):
#include<bits/stdc++.h>
#define puba push_back
using namespace std;
const char a[9] = {' ', 'P', 'K', 'D', 'F', 'N', 'W', 'J', 'Z'};
map<char, int>b;
int n, nn, m, num, siz[2], mp;
char w;
int fwj[2010];
int ned, who, where;
string name;
struct node{
int lf;
int nxt, las, t[10], id1, id2;
int z;
int vis;
vector<int>p;
}x[11];
stack<int>s;
void input(){
cin >> n >> m;
for(int i = 1; i <= n; ++i){
cin >> name;
x[i].lf = 4;
if(name == "MP") x[i].id1 = 1, x[i].id2 = 2, ++siz[0], mp = i;
if(name == "ZP") x[i].id1 = 2;
if(name == "FP") x[i].id1 = 3, ++siz[1];
for(int j = 1; j <= 4; ++j){
cin >> w; num = b[w];
x[i].p.puba(num); ++x[i].t[num];
}
x[i].nxt = i + 1;
x[i].las = i - 1;
if(i == 1) x[i].las = n;
if(i == n) x[i].nxt = 1;
}
for(int i = 1; i <= m; ++i){
cin >> w;
fwj[i] = b[w];
}
for(int i = m; i >= 1; --i) s.push(fwj[i]);
}
bool ck_rl(int a, int b){
if(x[a].id1 == 1 && (x[b].id2 == 3 || x[b].id2 == 4)){
return 1;
}
if(x[a].id1 == 2 && x[b].id2 == 3){
x[a].id2 = 2;
cerr<<a<<"变成好人\n";
return 1;
}
if(x[a].id1 == 3 && (x[b].id2 == 1 || x[b].id2 == 2)){
x[a].id2 = 3;
cerr<<a<<"变成坏人\n";
return 1;
}
return 0;
}
bool delet(int o, int ty, int w){
if(x[o].t[ty]){
cerr<<o<<"有"<<ty<<"这张牌,用掉\n";
--x[o].t[ty];
if(w != -1){
x[o].p.erase(x[o].p.begin() + w);
if(who == o && w <= where) --where;
}else{
for(int i = 0; i < x[o].p.size(); ++i){
if(x[o].p[i] == ty){
x[o].p.erase(x[o].p.begin() + i);
if(who == o && i <= where) --where;
break;
}
}
}
return 1;
}
return 0;
}
bool ck_lf(int o){
if(x[o].lf == 0){
if(!delet(o, 1, -1)){
cerr<<"没有桃,"<<o<<"死了\n";
x[x[o].las].nxt = x[o].nxt;
x[x[o].nxt].las = x[o].las;
--nn; x[o].vis = 1;
if(x[o].id1 == 3) --siz[1];
if(x[o].id1 == 1) --siz[0];
return 1;
}else{
cerr<<o<<"有桃,不死\n";
++x[o].lf;
}
}
return 0;
}
void ck_ws(int a, int b){
if(x[a].id1 == 1 && x[b].id1 == 2){
cerr<<"主公"<<a<<"把忠臣"<<b<<"误杀了,清空手牌\n";
for(int i = 1; i <= 8; ++i) x[a].t[i] = 0;
x[a].z = 0; x[a].p.clear();
}
}
void ck_zs(int a, int b){
if(x[b].id1 == 3){
x[a].p.puba(s.top()), x[a].t[s.top()]++; if(s.size() > 1) s.pop();
x[a].p.puba(s.top()), x[a].t[s.top()]++; if(s.size() > 1) s.pop();
x[a].p.puba(s.top()), x[a].t[s.top()]++; if(s.size() > 1) s.pop();
}
}
bool ck_end(){
cerr<<"剩余人数"<<siz[0]<<' '<<siz[1]<<' '<<!(siz[0] && siz[1])<<"\n";
return !(siz[0] && siz[1]);
}
bool query(int o, int ty){
int j = o, ans1 = 0, ans2 = 0;
do{
// cerr<<j<<' '<<o<<' '<<"fuck\n";
if((x[j].id2 == ty || x[j].id1 == ty) && delet(j, 7, -1)){
x[j].id2 = ty; ans1 = 1;
cerr<<j<<"使用无懈可击,他变成了"<<((ty == 3) ? "坏" : "好")<<"人。\n";
if(ty == 2) ans2 = query(j, 3);
else if(ty == 3) ans2 = query(j, 2);
break;
}
j = x[j].nxt;
}while(j != o);
if(ans1 ^ ans2) cerr<<j<<"的无懈可击有效\n";
else if(ans1) cerr<<j<<"的无懈可击无效\n";
return ans1 ^ ans2;
}
int pre(int o){
if(x[o].id1 == 1 || x[o].id1 == 2) return 2;
if(x[o].id1 == 3) return 3;
}
void print(){
for(int i = 1; i <= n; ++i){
cerr<<i<<":\n";
cerr<<"血量"<<x[i].lf<<"\n";
cerr<<"状态"<<x[i].id2<<'\n';
if(x[i].vis) cerr<<"DEAD";
else{
for(auto j : x[i].p){
cerr<<j<<' ';
}
}
cerr<<'\n';
}
}
void op(){
int o = 1, killed = 0;
while(siz[0] && siz[1]){
x[o].p.puba(s.top()), x[o].t[s.top()]++; if(s.size() > 1) s.pop();
x[o].p.puba(s.top()), x[o].t[s.top()]++; if(s.size() > 1) s.pop();
killed = 0;
int i = 0;
who = o;
while(i < x[o].p.size()){
where = i;
cerr<<o<<"人的"<<i + 1<<"张牌"<<x[o].p[i]<<"\n";
if(x[o].p[i] == 1){ //桃
if(x[o].lf < 4){
cerr<<o<<"使用一张桃\n";
++x[o].lf;
delet(o, 1, i); i = where;
}
}else
if(x[o].p[i] == 2){//杀
if(ck_rl(o, x[o].nxt) && ( (!killed) || x[o].z)){
cerr<<o<<"对"<<x[o].nxt<<"使用一张杀\n";
delet(o, 2, i); i = where;
if(!delet(x[o].nxt, 3, -1)){
i = where;
cerr<<x[o].nxt<<"没有闪,扣血\n";
--x[x[o].nxt].lf; int zs = x[o].nxt;
if(ck_lf(x[o].nxt)){
if(ck_end()) break;
ck_ws(o, zs);
ck_zs(o, zs);
}
}else{
cerr<<x[o].nxt<<"有闪\n";
}
killed = 1;
if(ck_end()) break;
}
}else
if(x[o].p[i] == 4){//决斗
int used = 0;
for(int j = x[o].nxt; j != o; j = x[j].nxt){
if(x[o].id1 == 3 && x[j].id1 != 1) continue;
// cerr<<"a"<<i<<' '<<j<<'\n';
if(ck_rl(o, j)){
cerr<<o<<"对"<<j<<"使用一张决斗\n";
delet(o, 4, i); i = where;
if(x[j].id2 != 0 && x[j].id2 != 4 && query(o, pre(j)) ){
cerr<<j<<"被保护\n";
break;
}
cerr<<"开始决斗\n";
cerr<<"杀的个数分别为:"<<x[o].t[2]<<' '<<x[j].t[2]<<'\n';
if(x[o].t[2] >= x[j].t[2] || (x[o].id1 == 1 && x[j].id1 == 2)){
--x[j].lf;
cerr<<j<<"扣血\n";
for(int k = 1; k <= x[j].t[2]; ++k){
delet(o, 2, -1); delet(j, 2, -1);
}
i = where;
if(ck_lf(j)){
if(ck_end()) break;
ck_ws(o, j);
ck_zs(o, j);
}
}else{
--x[o].lf;
cerr<<o<<"扣血\n";
for(int k = 1; k <= x[o].t[2]; ++k){
delet(o, 2, -1); delet(j, 2, -1);
}
delet(j, 2, -1);
i = where;
if(ck_lf(o)){
if(ck_end()) break;
ck_ws(j, o);
ck_zs(j, o);
break;
}
}
where = i = -1;
break;
}
}
if(x[o].vis) break;
if(ck_end()) break;
}else
if(x[o].p[i] == 5 || x[o].p[i] == 6){//南蛮/万箭
int g = x[o].p[i] - 3;
if(x[o].p[i] == 5) cerr<<o<<"使用南蛮入侵\n";
if(x[o].p[i] == 6) cerr<<o<<"使用万箭齐发\n";
delet(o, x[o].p[i], i); i = where;
for(int j = x[o].nxt; j != o; j = x[j].nxt){
if(x[j].id2 != 0 && x[j].id2 != 4 && query(o, pre(j))){
cerr<<j<<"被保护\n";
continue;
}
if(!delet(j, g, -1)){
--x[j].lf;
cerr<<j<<"扣血\n";
if(ck_lf(j)){
if(ck_end()) break;
ck_ws(o, j);
ck_zs(o, j);
}
if(x[j].id1 == 1 && x[o].id2 == 0){
cerr<<o<<"被标记为类反猪\n";
x[o].id2 = 4;
}
}else{
if(g == 2) cerr<<j<<"有杀\n";
if(g == 3) cerr<<j<<"有闪\n";
}
}
where = i = -1;
if(ck_end()) break;
}else
if(x[o].p[i] == 8){
cerr<<o<<"装备诸葛连弩\n";
x[o].z = 1;
delet(o, 8, i);i = where;
i = where = -1;
if(ck_end()) break;
}
i = where;
cerr<<i<<" "<<x[o].p.size();
++i;
if(ck_end()) break;
}
if(ck_end()) break;
print();
o = x[o].nxt;
}
}
void output(){
if(siz[0] == 0) cout<<"FP\n";
if(siz[1] == 0) cout<<"MP\n";
for(int i = 1; i <= n; ++i){
if(x[i].vis) cout<<"DEAD";
else{
for(auto j : x[i].p){
cout<<a[j]<<' ';
}
}
cout<<'\n';
}
}
int main(){
// freopen("1.in","r",stdin);
// freopen("1.out","w",stdout);
for(int i = 1; i <= 8; ++i) b[a[i]] = i;
input();
for(int i = 1; i <= n; ++i){
cerr<<i<<":\n";
cerr<<"血量"<<x[i].lf<<"\n";
cerr<<"状态"<<x[i].id2<<'\n';
if(x[i].vis) cerr<<"DEAD";
else{
for(auto j : x[i].p){
cerr<<j<<' ';
}
}
cerr<<'\n';
}
op();
output();
}