记录编号 546904 评测结果 AAAAAAAAAAAAAAAAAAAA
题目名称 [SDOI 2010] 猪国杀 最终得分 100
用户昵称 Gravatar斯内普和骑士 是否通过 通过
代码语言 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; 
}