题目大意:出题人给你指定了一种全新形式的自动三国杀规则,你来模拟这个过程(BZOJ题面不全,可以参考这个网站,题面很不错)
真的是一道清新可人的题呢!
//做题过程
从昨天下午4点开始写的,认认真真的写到了6点,然后去看球了...
看球的时候也写了一点点,到晚上8点一共写了6KB左右的样子
今天上午考完试之后就一直在写,大约在三点左右第一次点了编译,当时大约400行,8KB左右吧
三点半左右终于过了编,然后就是样例死循环
过了样例已经四点二十了,交了一发TLE(死循环),于是要来了数据慢慢弄
七点半AC
//做题总结
我认为这道题是一道不错的题,可以锻炼思维
这个思维不是通常的想题的思维,而是对程序整体框架的构思,我认为这个是非常重要的
写代码之前就应该大概想好框架,要不然容易出现写着写着还要推掉,还不忍心删掉的窘境
其次,这道题可以考察选手的耐心,以及...调试功底....还有....码力
这道题在2010年出到SD的省选是不是有点丧心病狂啊,根本不会有人去做好吗,(要是放到2015的AH还差不多)
做完这道题整个人都释然了
以后还会不会去碰三国杀呢?.....
//本题细节
这道题没什么题解好写....
你要记得玩家是猪!!!!!!他们会干出很多匪夷所思的事情!!
说说我出现过的所有错误吧
1.打出牌时手牌链表的头尾要注意更新
2.最开始的时候要把所有反贼的第一目标设为主公
3.反贼的决斗都会直接打向主公
4.有人死亡的时候要重新更新第一目标
5.出锦囊的人是有可能无懈掉这个锦囊的
6.出决斗的人可能死在自己回合里,这时候立即终止他的出牌阶段
7.主公杀死忠臣要扔掉诸葛连弩
8.有人在自己回合打出牌的时候,应该重置当前扫描位置(我的做法是这样)
//本题坑点
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 5010
using namespace std;
int bef[N],nxt[N],cnt;char kind[N];//所有玩家的手牌
char PaiDui[3010];int Top,m;//牌堆
char MoPai()//摸走牌堆顶的牌,(如果没牌就一直抽最后一张)
{
if(Top!=m) Top++;
return PaiDui[Top];
}
int ASF[11];//真实身份 1主公 2忠臣 3反贼
int totF;//剩余反贼
bool GameOver;//游戏是否结束
int NowRound;//当前是谁的回合
void Sha(int,int);
void Fight(int,int);
void Nanman(int);
void Wanjian(int);
class Pig
{
public:
int CSF;//目前身份 0没跳 1类反 2跳忠 3跳反
int head,last,now,TMP;//手牌链表
int blood;//血量
int totwx;//手中无懈可击数量
int totp;//手中桃的数量
int tots;//手中闪的数量
int Atk;//首要攻击目标
int befpig,nxtpig;//存活的上一头猪和下一头猪
bool dead;//是否死了
bool Zhuge;//是否装备诸葛连弩
int num;//你是哪头?
//调试区域开始
void ShouPai()
{
int now=head;
cout<<blood<<' ';
while(now)
{
cout<<kind[now];
now=nxt[now];
}
cout<<endl;
}
//调试区域结束
void Bonus()
{
cnt++;kind[cnt]=MoPai();bef[cnt]=last;
if(head==0) head=last=cnt;
else nxt[last]=cnt,last=cnt;
if(kind[cnt]=='J') totwx++;
if(kind[cnt]=='P') totp++;
if(kind[cnt]=='D') tots++;
cnt++;kind[cnt]=MoPai();bef[cnt]=last;
nxt[last]=cnt,last=cnt;
if(kind[cnt]=='J') totwx++;
if(kind[cnt]=='P') totp++;
if(kind[cnt]=='D') tots++;
cnt++;kind[cnt]=MoPai();bef[cnt]=last;
nxt[last]=cnt,last=cnt;
if(kind[cnt]=='J') totwx++;
if(kind[cnt]=='P') totp++;
if(kind[cnt]=='D') tots++;
}
void Punish()
{
head=last=now=0;
totwx=totp=tots=0;
Zhuge=false;
}
void MoPaiStage()//摸牌阶段
{
cnt++;kind[cnt]=MoPai();bef[cnt]=last;
if(head==0) head=last=cnt;
else nxt[last]=cnt,last=cnt;
if(kind[cnt]=='J') totwx++;
if(kind[cnt]=='P') totp++;
if(kind[cnt]=='D') tots++;
cnt++;kind[cnt]=MoPai();bef[cnt]=last;
nxt[last]=cnt,last=cnt;
if(kind[cnt]=='J') totwx++;
if(kind[cnt]=='P') totp++;
if(kind[cnt]=='D') tots++;
}
void Use(int x)//使用一张牌(让其从链表中消失)
{
if(kind[x]=='J') totwx--;
if(kind[x]=='P') totp--;
if(kind[x]=='D') tots--;
if(x==head&&x==last) head=0,last=0;
else if(x==head) head=nxt[x],bef[nxt[x]]=0;
else if(x==last) last=bef[x],nxt[bef[x]]=0;
else bef[nxt[x]]=bef[x],nxt[bef[x]]=nxt[x];
// cout<<x<<' '<<head<<endl;
}
char Getnxt()//返回now的下一张手牌
{
if(!now) return 0;
TMP=now;
now=nxt[now];
// cout<<kind[tmp];
return kind[TMP];
}
void Output()//输出答案
{
if(dead) puts("DEAD");
else
{
while(head!=0)
{
// printf("%c",&kind[head]);
cout<<kind[head];
if(head!=last) cout<<' ';
head=nxt[head];
}
puts("");
}
}
int finds()//返回第一张闪的编号
{
now=head;
char tmp;
while(tmp=Getnxt())
if(tmp=='D') return TMP;
}
int findp()//返回第一张桃的编号
{
now=head;
char tmp;
while(tmp=Getnxt())
if(tmp=='P') return TMP;
}
int findwx()//返回第一张无懈可击的编号
{
now=head;
char tmp;
while(tmp=Getnxt())
if(tmp=='J') return TMP;
}
bool Qiusha()//尝试打出一张杀
{
now=head;
char tmp;
while(tmp=Getnxt())
if(tmp=='K')
{
Use(TMP);
return true;
}
return false;
}
bool Qiushan()//尝试打出一张闪
{
if(tots) {Use(finds());return true;}
return false;
}
bool QiuTao()//尝试给出一张桃
{
if(totp) {Use(findp());return true;}
return false;
}
bool Qiuwx()//尝试打出一张无懈可击
{
if(totwx) {Use(findwx());return true;}
return false;
}
void Round()//每头猪的回合
{
MoPaiStage();
now=head;
char tmp;
bool usedsha=false;
// cout<<endl;
while((tmp=Getnxt())&&!GameOver)
{
// cout<<tmp<<' ';
if(tmp=='D'||tmp=='J') continue;
if(tmp=='P')
{
if(blood!=4) blood++,Use(TMP);
continue;
}
if(tmp=='K')
{
if(Atk==nxtpig)
{
if(!usedsha||Zhuge)
{
Use(TMP),Sha(num,Atk);
now=head;
usedsha=true;
if(GameOver) return;
}
}
continue;
}
if(tmp=='F')
{
if(!Atk) continue;
Use(TMP);
if(ASF[num]==3) Fight(num,1);
else Fight(num,Atk);
now=head;
if(GameOver||dead) return;
continue;
}
if(tmp=='N')
{
Use(TMP);
Nanman(num);
now=head;
if(GameOver) return;
continue;
}
if(tmp=='W')
{
Use(TMP);
Wanjian(num);
now=head;
if(GameOver) return;
continue;
}
if(tmp=='Z')
{
Use(TMP);
Zhuge=true;
now=head;
continue;
}
}
}
}pig[11];
void Recal(int x)
{
int y=pig[x].nxtpig;
if(ASF[x]==1)
{
while(y!=x)
{
if(pig[y].CSF==1||pig[y].CSF==3)
{
pig[x].Atk=y;
return;
}
y=pig[y].nxtpig;
}
pig[x].Atk=0;
}
else if(ASF[x]==2)
{
while(y!=x)
{
if(pig[y].CSF==3)
{
pig[x].Atk=y;
return;
}
y=pig[y].nxtpig;
}
pig[x].Atk=0;
}
else
{
while(y!=x)
{
if(pig[y].CSF==2||ASF[y]==1)
{
pig[x].Atk=y;
return;
}
y=pig[y].nxtpig;
}
pig[x].Atk=0;
}
}
void Allrecal()
{
int x=pig[1].nxtpig;
Recal(1);
while(x!=1)
{
Recal(x);
x=pig[x].nxtpig;
}
}
void Kill(int x,int y)
{
pig[y].dead=true;
if(ASF[y]==1) {GameOver=true;return;}
if(ASF[y]==3)
{
totF--;
if(totF==0) {GameOver=true;return;}
pig[x].Bonus();
}
if(ASF[y]==2&&ASF[x]==1)
pig[x].Punish();
int BEF=pig[y].befpig,NXT=pig[y].nxtpig;
pig[BEF].nxtpig=NXT;
pig[NXT].befpig=BEF;
Allrecal();
}
void Hurt(int x,int y)
{
pig[y].blood--;
if(pig[y].blood==0)
{
if(pig[y].QiuTao()) pig[y].blood++;
else Kill(x,y);
}
}
void Sha(int x,int y)//杀事件
{
if(ASF[x]!=1&&pig[x].CSF<2)
{
if(ASF[y]==3) pig[x].CSF=2;
else pig[x].CSF=3;
Allrecal();
}
if(pig[y].Qiushan()) return;
Hurt(x,y);
}
bool startwxcycle(int st,bool YisFan)
{
bool ST=YisFan;
int lastdachu=st,x=st;
if(YisFan==(ASF[x]==3))
{
if(pig[x].Qiuwx())
{
lastdachu=x;
YisFan^=1;
if(pig[x].CSF<=2)
{
pig[x].CSF=3-YisFan;
Allrecal();
}
}
}
x=pig[x].nxtpig;
while(x!=lastdachu)
{
if(YisFan==(ASF[x]==3))
{
if(pig[x].Qiuwx())
{
lastdachu=x;
YisFan^=1;
if(pig[x].CSF<=2)
{
pig[x].CSF=3-YisFan;
Allrecal();
}
}
}
x=pig[x].nxtpig;
}
return (ST!=YisFan);
}
void Fight(int x,int y)//决斗事件
{
if(ASF[x]!=1&&pig[x].CSF<2)
{
if(ASF[y]==3) pig[x].CSF=2;
else pig[x].CSF=3;
Allrecal();
}
if(ASF[y]==1||pig[y].CSF>=2)
{
if(ASF[y]==1||pig[y].CSF==2)
{
if(startwxcycle(x,0))
return;
}
else
{
if(startwxcycle(x,1))
return;
}
}
if(ASF[x]==1&&ASF[y]==2)
Hurt(x,y);
else
{
while(1)
{
if(!pig[y].Qiusha()) {Hurt(x,y);return;}
if(!pig[x].Qiusha()) {Hurt(y,x);return;}
}
}
}
void Nanman(int x)//南蛮事件
{
int y=pig[x].nxtpig;
while(y!=x)
{
if(ASF[y]==1||pig[y].CSF>=2)
{
if(ASF[y]==1||pig[y].CSF==2)
{
if(startwxcycle(x,0))
{
y=pig[y].nxtpig;
continue;
}
}
else
{
if(startwxcycle(x,1))
{
y=pig[y].nxtpig;
continue;
}
}
}
if(!pig[y].Qiusha())
{
Hurt(x,y);
if(GameOver) return;
if(y==1&&pig[x].CSF==0)
{
pig[x].CSF=1;
Allrecal();
}
}
y=pig[y].nxtpig;
}
}
void Wanjian(int x)//万箭事件
{
int y=pig[x].nxtpig;
while(y!=x)
{
if(ASF[y]==1||pig[y].CSF>=2)
{
if(ASF[y]==1||pig[y].CSF==2)
{
if(startwxcycle(x,0))
{
y=pig[y].nxtpig;
continue;
}
}
else
{
if(startwxcycle(x,1))
{
y=pig[y].nxtpig;
continue;
}
}
}
if(!pig[y].Qiushan())
{
Hurt(x,y);
if(GameOver) return;
if(y==1&&pig[x].CSF==0)
{
pig[x].CSF=1;
Allrecal();
}
}
y=pig[y].nxtpig;
}
}
int main()
{
// freopen("kopk6.in","r",stdin);
int n;
scanf("%d%d",&n,&m);
int i,j,x=0,y;
char o[10];
for(i=1;i<n;i++) pig[i].nxtpig=i+1;pig[n].nxtpig=1;
for(i=2;i<=n;i++) pig[i].befpig=i-1;pig[1].befpig=n;
for(i=1;i<=n;i++)
{
scanf("%s",o);
if(o[0]=='M') ASF[i]=1;
else if(o[0]=='Z') ASF[i]=2;
else if(o[0]=='F') ASF[i]=3,totF++;
scanf("%s",o);x++;PaiDui[x]=o[0];
scanf("%s",o);x++;PaiDui[x]=o[0];
scanf("%s",o);x++;PaiDui[x]=o[0];
scanf("%s",o);x++;PaiDui[x]=o[0];//先把牌都插到牌堆里
}
for(i=1;i<=m;i++)
scanf("%s",o),x++,PaiDui[x]=o[0];
m+=4*n;
for(i=1;i<=n;i++)
{
pig[i].MoPaiStage();pig[i].MoPaiStage();
pig[i].num=i;
pig[i].blood=4;//初始化每头猪
}
i=1;
Allrecal();
while(!GameOver)
{
NowRound=i;
/* for(j=1;j<=n;j++)
pig[j].ShouPai();
cout<<endl;*/
pig[i].Round();
/* for(j=1;j<=n;j++)
pig[j].ShouPai();
cout<<endl;*/
i=pig[i].nxtpig;
}
if(pig[1].dead) puts("FP");
else puts("MP");
for(i=1;i<=n;i++)
pig[i].Output();
}