[SDOI2010]猪国杀
猪国杀
https://ac.nowcoder.com/acm/problem/210160
暴力模拟。
认真读题,并将所有信息列在草稿中。对于这种大模拟。
代码里有一些必要的注释。
#include<bits/stdc++.h> using namespace std; const int N=2050,M=25; int n; int fpcout;//反猪数目. bool missionFinished;//游戏结束. int totcard,nowcard;//总牌数,现取牌数. char cardset[N],identify[M];//以'U'来表示未知,'L'表示类反. struct Player{ bool army;//猪哥连弩. int cout,hp,nxt,prv; char identify,cards[N]; }a[N]; void getcard(int id){ if(nowcard==totcard) nowcard--; a[id].cards[++a[id].cout]=cardset[++nowcard]; return ; } void clear(int id){ a[id].cout=0; a[id].army=false; memset(a[id].cards,0,sizeof a[id].cards); return ; } void killplayer(int killedid,int killerid){ //尝试 桃. for(int i=1; i<=a[killedid].cout; ++i){ if(a[killedid].cards[i]=='P'){ a[killedid].cards[i]=0; a[killedid].hp++; return ; } } //没有. //更换顺序. a[a[killedid].prv].nxt=a[killedid].nxt; a[a[killedid].nxt].prv=a[killedid].prv; if(a[killedid].identify=='M'){//mission failed. missionFinished=true; return ; } if(a[killedid].identify=='F'){ fpcout--; if(fpcout==0){//mission complete missionFinished=true; return ; } getcard(killerid); getcard(killerid); getcard(killerid); } if(a[killedid].identify=='Z' && a[killerid].identify=='M') clear(killerid); return ; } void attack(int attackedid,int attackerid){ //尝试 闪. for(int i=1; i<=a[attackedid].cout; ++i){ if(a[attackedid].cards[i]=='D'){ a[attackedid].cards[i]=0; return ; } } //没有闪. --a[attackedid].hp; if(a[attackedid].hp==0) killplayer(attackedid,attackerid); return ; } bool unattackable(int attackerid,int attackedid,bool mode){//能跳则跳. //printf("%d %d %d\n",attackerid,attackedid,mode); bool flag=true; for(int i=attackerid; i!=attackerid||flag; i=a[i].nxt){ flag=false; if(mode==1){ //献殷勤. if((a[i].identify==identify[attackedid]) || (a[i].identify=='Z' && identify[attackedid]=='M') || (a[i].identify=='M' && identify[attackedid]=='Z')){ for(int j=1; j<=a[i].cout; ++j){ if(a[i].cards[j]=='J'){ a[i].cards[j]=0; identify[i]=a[i].identify; return !unattackable(i,attackerid,!mode); } } } }else{ //表敌意. if(((a[i].identify=='Z' || a[i].identify=='M') && identify[attackerid]=='F') || (a[i].identify=='F' && (identify[attackerid]=='Z' || identify[attackerid]=='M'))){ for(int j=1; j<=a[i].cout; ++j){ if(a[i].cards[j]=='J'){ a[i].cards[j]=0; identify[i]=a[i].identify; return !unattackable(i,attackerid,mode); } } } } } return false; } void invasion(int invader,char way){ for(int i=a[invader].nxt; i!=invader; i=a[i].nxt){ if(unattackable(invader,i,1)==false){ int j=0; for(j=1; j<=a[i].cout; ++j){ if(a[i].cards[j]==way){ a[i].cards[j]=0; break; } } if(j>a[i].cout){ a[i].hp--; if(i==1 && identify[invader]==0) identify[invader]='L'; if(a[i].hp==0) killplayer(i,invader); if(missionFinished==true) return ; } } } return ; } void fight(int fightedid,int fighterid){ if(unattackable(fighterid,fightedid,1)==false){ if(fighterid==1 && a[fightedid].identify=='Z'){//忠猪不会抵抗主猪的决斗. --a[fightedid].hp; if(a[fightedid].hp==0) killplayer(fightedid,fighterid); } else{ int j=1,k=1;//两人目前枚举到的牌的位置. while(1){ while(j<=a[fightedid].cout && a[fightedid].cards[j]!='K') ++j; if(j<=a[fightedid].cout) a[fightedid].cards[j]=0;//出杀. else{ --a[fightedid].hp; if(a[fightedid].hp==0) killplayer(fightedid,fighterid); break; } while(k<=a[fighterid].cout && a[fighterid].cards[k]!='K') ++k; if(k<=a[fighterid].cout) a[fighterid].cards[k]=0; else{ --a[fighterid].hp; if(a[fighterid].hp==0) killplayer(fighterid,fightedid); break; } } } } return ; } void start(){ missionFinished=false; if(fpcout==0) return ;//无反猪,主猪胜. for(int i=1; i; i=a[i].nxt){ getcard(i); getcard(i); bool attacked=false;//是否已经使用过杀. for(int j=1; j<=a[i].cout; ++j){ if(a[i].cards[j]!=0){ if(a[i].hp==0) break; char nowcard=a[i].cards[j]; if(nowcard=='P' && a[i].hp<4){ a[i].hp++; a[i].cards[j]=0; } else if(nowcard=='K' && (a[i].army==true || attacked==false)){ if(a[i].identify=='Z' && identify[a[i].nxt]!='F') continue; if(a[i].identify=='M' && identify[a[i].nxt]!='F' && identify[a[i].nxt]!='L') continue; if(a[i].identify=='F' && identify[a[i].nxt]!='Z' && identify[a[i].nxt]!='M') continue; a[i].cards[j]=0; attack(a[i].nxt,i); attacked=true; identify[i]=a[i].identify;//暴露身份. if(missionFinished==true) return ; } else if(nowcard=='F'){ if(a[i].identify=='F'){//优先攻击主猪. a[i].cards[j]=0; fight(1,i); identify[i]='F'; if(missionFinished==true) return ; j=0;//recheck. }else{ for(int k=a[i].nxt; k!=i; k=a[k].nxt){//寻找'F','L'. if((a[i].identify=='Z' && identify[k]=='F') || (a[i].identify=='M' && (identify[k]=='F' || identify[k]=='L'))){ a[i].cards[j]=0; fight(k,i); identify[i]=a[i].identify; if(missionFinished==true) return ; j=0; break; } } } } else if(nowcard=='Z'){ a[i].cards[j]=0; a[i].army=true; j=0; } else if(nowcard=='W'){ a[i].cards[j]=0; invasion(i,'D'); if(missionFinished==true) return ; j=0; } else if(nowcard=='N'){ a[i].cards[j]=0; invasion(i,'K'); if(missionFinished==true) return ; j=0; } } } } return ; } void over(){ puts(a[1].hp<=0 ? "FP" : "MP"); for(int i=1 ; i<=n; ++i){ if(a[i].hp<=0) puts("DEAD"); else{ for(int j=1; j<=a[i].cout; ++j) if(a[i].cards[j]!=0) printf("%c ",a[i].cards[j]); printf("\n"); } } return ; } void Init(){ for(int i=1; i<=n; ++i){ a[i].nxt=i+1; a[i].prv=i-1; } a[n].nxt=1,a[1].prv=n; static char buf[1000005]; for(int i=1; i<=n; ++i){ scanf("%s",buf);//读取身份. a[i].identify=buf[0]; for(int j=1; j<=4; ++j){ scanf("%s",buf); a[i].cards[j]=buf[0]; } a[i].cout=a[i].hp=4; if(a[i].identify=='F') fpcout++;//记录反猪数目. } // printf("%d\n",fpcout); identify[1]='M';//1号为主猪. for(int i=1; i<=totcard; ++i){ scanf("%s",buf); cardset[i]=buf[0]; } return ; } int main(){ scanf("%d%d",&n,&totcard); Init(); start(); over(); return 0; }