记录编号 |
546904 |
评测结果 |
AAAAAAAAAAAAAAAAAAAA |
题目名称 |
[SDOI 2010] 猪国杀 |
最终得分 |
100 |
用户昵称 |
斯内普和骑士 |
是否通过 |
通过 |
代码语言 |
C++ |
运行时间 |
0.036 s |
提交时间 |
2019-11-14 16:46:57 |
内存使用 |
13.70 MiB |
显示代码纯文本
#include<bits/stdc++.h>
using namespace std;
struct node
{
int cs,hp,next,last;//总共容纳牌量,血量,左边的玩家,右边的玩家
char id,card[2010];//该玩家ID,是主公还是忠臣还是反贼,和手牌
bool zgln;//是否装备X弩
}a[20];//玩家信息
char kn[11],kpd[2010],sss[10];
int n,m,fz;
bool ed;
void mp(int x)//令x摸牌
{
if(!m)
m++;
a[x].card[++a[x].cs]=kpd[m];
m--;
}
void js(int x1,int x2)//x1-->kill x2
{
for(int i=1;i<=a[x2].cs;i++)
if(a[x2].card[i]=='P')//判桃
{
a[x2].card[i]='U';
a[x2].hp++;
return;
}
a[a[x2].next].last=a[x2].last;//距离改变
a[a[x2].last].next=a[x2].next;
if(x2==1)
{
ed=true;
return;
}
if(a[x2].id=='F')
fz--;//击杀一个反贼需要减掉一个反贼
if(!fz)
{
ed=true;
return;
}//反贼死完游戏结束
if(a[x2].id=='F')
mp(x1),mp(x1),mp(x1);
if(a[x2].id=='Z'&&a[x1].id=='M')//主公杀了忠臣掉所有装备,因为他是个疯子
a[x1].cs=0,a[x1].zgln=false;
}
void Kil(int x1,int x2)//x1-->用杀对x2
{
for(int i=1;i<=a[x2].cs;i++)
if(a[x2].card[i]=='D')
{
a[x2].card[i]='U';
return;
}//每次出杀,遍历一遍牌,寻找是否有闪,无闪扣血
a[x2].hp--;//伤害减掉1
if(!a[x2].hp)
js(x1,x2);//判断是否击杀
}
bool wxkj(int x1,int x2,int x3)//无懈可击 x1-->x2使用,x3为判
{
int i=x1,pd=x3?x2:x1;//结果为真则为x2,结果为假则为x1
while(1)
{
if(x3==1)
{
if(kn[x2]==a[i].id||(kn[x2]=='M'&&a[i].id=='Z')||(kn[x2]=='Z'&&a[i].id=='M'))
for(int j=1;j<=a[i].cs;j++)
if(a[i].card[j]=='J')//遍历无懈可击
{
a[i].card[j]='U';
kn[i]=a[i].id;
return !wxkj(i,x1,0);//轮回
}
}
else
{
if(((a[i].id=='M'||a[i].id=='Z')&&kn[x1]=='F')||(a[i].id=='F'&&(kn[x1]=='M'||kn[x1]=='Z')))
for(int j=1;j<=a[i].cs;j++)//仍然遍历无懈可击
if(a[i].card[j]=='J')
{
a[i].card[j]='U';
kn[i]=a[i].id;
return !wxkj(i,x1,0);
}
}
i=a[i].next;
if(i==x1)
break;//无人用无懈可击就成功打断
}
return false;
}
void nmrq(int x1)//x1发动让人恶心的南蛮入侵了
{
for(int x2=a[x1].next;x2!=x1;x2=a[x2].next)//循次出牌,出杀可挡,不出杀则扣血,当然也可用某些操作处理掉
if(!wxkj(x1,x2,1))//无懈可击使用时它将无法生效,若没有无懈可击挡,出招成功
{
int i;
for(i=1;i<=a[x2].cs;i++)
if(a[x2].card[i]=='K')
{
a[x2].card[i]='U';
break;
}
if(i>a[x2].cs)
{
a[x2].hp--;
if(x2==1&&kn[x1]=='U')
kn[x1]='L';
if(!a[x2].hp)
js(x1,x2);
if(ed)
return;
}
}
}
void wjqf(int x1)//万箭齐发与南蛮入侵相同,但是要出闪而不是杀
{
for(int x2=a[x1].next;x2!=x1;x2=a[x2].next)
if(!wxkj(x1,x2,1))
{
int i;
for(i=1;i<=a[x2].cs;i++)
if(a[x2].card[i]=='D')
{
a[x2].card[i]='U';
break;
}
if(i>a[x2].cs)
{
a[x2].hp--;
if(x2==1&&kn[x1]=='U')
kn[x1]='L';
if(!a[x2].hp)
js(x1,x2);
if(ed)
return;
}
}
}
void jd(int x1,int x2)//x1-->x2决斗
{
int i,j,k;
if(wxkj(x1,x2,1))
return;//存在无懈可击就GG
if(x1==1&&a[x2].id=='Z')
{
a[x2].hp--;
if(!a[x2].hp)
js(x1,x2);
return;
}//存在主公错攻忠臣,而忠臣会选择不反抗,自己自动扣血
//正常
j=k=1;
while(1)
{
while(a[x2].card[j]!='K'&&j<=a[x2].cs)//先从x2开始到x1,然后循环往复,有一人扣血就出循环
j++;
if(j>a[x2].cs)
{
a[x2].hp--;
if(!a[x2].hp)
js(x1,x2);
return;
}
else
a[x2].card[j]='U';
while(a[x1].card[k]!='K'&&k<=a[x1].cs)
k++;
if(k>a[x1].cs)
{
a[x1].hp--;
if(!a[x1].hp)
js(x2,x1);
return;
}
else
a[x1].card[k]='U';
}
}
void CTJ()//万能CTJ函数
{
char nc;//现在的手牌
ed=true;
if(fz)
ed=false;
if(ed)
return;//啥都没干就过T T
for(int i=1;i;i=a[i].next)//从主公开始,RUA
{
mp(i),mp(i);//摸牌两张,看能不能碰上运气
bool kill=true;
for(int j=1;j<=a[i].cs;j++)
if(a[i].card[j]!='U')//若为正常手牌
{
if(!a[i].hp)
break;//死玩家可不能乱来
nc=a[i].card[j];
if(nc=='P')//桃补血
{
if(a[i].hp!=4)
a[i].hp++,a[i].card[j]='U';
continue;
}
if(nc=='K')//出杀
{
if(!kill&&!a[i].zgln)
continue;//如果出一次杀而无X弩继续攻击,那就很难受了xixi
if(a[i].id=='M'&&kn[a[i].next]!='L'&&kn[a[i].next]!='F')//类反贼和反贼主公都会攻击
continue;
if(a[i].id=='Z'&&kn[a[i].next]!='F')//忠臣只攻击反贼
continue;
if(a[i].id=='F'&&kn[a[i].next]!='Z'&&kn[a[i].next]!='M') //反贼攻击主公和忠臣
continue;
a[i].card[j]='U';//出该牌
Kil(i,a[i].next);
kn[i]=a[i].id,kill=false;
if(ed)
return;
continue;
}
if(nc=='F')
{
if(a[i].id=='F')
{
a[i].card[j]='U',jd(i,1);
kn[i]=a[i].id;
if(ed)
return;
j=0;
continue;
}
for(int k=a[i].next;k!=i;k=a[k].next)
if((a[i].id=='M'&&(kn[k]=='L'||kn[k]=='F'))||(a[i].id=='Z'&&kn[k]=='F'))
{
a[i].card[j]='U',jd(i,k);
kn[i]=a[i].id;
if(ed)
return;
j=0;
break;
}
continue;
}
if(nc=='N')
{
a[i].card[j]='U';
nmrq(i);
if(ed)
return;
j=0;
continue;
}
if(nc=='W')
{
a[i].card[j]='U';
wjqf(i);
if(ed)
return;
j=0;
continue;
}
if(nc=='Z')
{
a[i].zgln=true;
a[i].card[j]='U';
j=0;
continue;
}
}
}
}
int main()
{
freopen("kopk.in","r",stdin);
freopen("kopk.out","w",stdout);
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++)
a[i].next=i+1,a[i].last=i-1;
a[n].next=1,a[1].last=n;
for(int i=1;i<=n;i++)
{
for(int j=1;j<2010;j++)
a[i].card[j]='U';
scanf("%s",sss);
a[i].id=sss[0];
for(int j=1;j<=4;j++)
scanf("%s",sss),a[i].card[j]=sss[0];
a[i].cs=a[i].hp=4;
if(a[i].id=='F')
fz++;//反贼RUA
a[i].zgln=false;//不能开挂的嘻嘻
}
for(int i=2;i<=n;i++)
kn[i]='U';
kn[1]='M';
for(int i=1;i<=m;i++) scanf("%s",sss),kpd[m-i+1]=sss[0];
CTJ();//回合.......CTJ函数
if(a[1].hp<=0) printf("FP\n");
else printf("MP\n");
//看看主公有没有挂
for(int i=1;i<=n;i++)
{
if(a[i].hp<=0) printf("DEAD\n");
//空血凉凉
else
//亮牌
{
for(int j=1;j<=a[i].cs;j++)
if(a[i].card[j]!='U') printf("%c ",a[i].card[j]);
//若该手牌没有被弃置则输出
printf("\n");
}
}
return 0;
}