题解 [SDOI2010]猪国杀

代码成功卡到(600)行以内

曾经发誓一天切掉的我打了两周。。。

先看题

要点还是挺多的,即使是像我这样熟悉三国杀的同(wán)学(jiā),也要认真看。


首先是基本牌的部分。

杀:在自己的回合内,对攻击范围内除自己以外的一名角色使用。如果没有被『闪』抵消,则造成1点伤害。无论有无武器,杀的攻击范围都是1;

直接看看自己的下家跳没跳,跳了的话就看看是不是一伙然后一刀砍下去,没跳直接(return)

注意,用了杀之后自己的身份就完全暴露了。


闪:当你受到杀的攻击时,可以弃置一张闪来抵消杀的效果;

这个没什么需要解释的吧,直接暴力看看有没有闪就行了。


桃:在自己的回合内,如果自己的体力值不等于体力上限,那么使用一个桃可以为自己补充一点体力,否则不能使用桃;桃只能对自己使用;在自己的回合外,如果自己的血变为0或者更低,那么也可以使用;

注意:不能对别人使用!!!


猪哥连弩:武器,攻击范围1,出牌阶段你可以使用任意张杀;

注意:即使之前有了也要再装一遍,把之前的顶掉(不愧是猪)。


看上去很简单,但是细节很多。

首先就是装上猪哥连弩之后前面的杀也是可以用的,需要(i=0)重新扫一遍。

还有题目描述中说保证牌数够用,不要相信它,牌堆没了就一直摸最后一张牌。

一个回合只能用一次杀(除非装了猪哥连弩)。


好了现在(10)分到手了。

接下来我们看锦囊牌。

决斗:出牌阶段,对除自己以外任意一名角色使用,由目标角色先开始,自己和目标角色轮流弃置一张杀,首先没有杀可弃的一方受到1点伤害,另一方视为此伤害的来源;

这个就一个(while)就暴力判断一下有没有杀就完事了,需要注意的是忠臣接收到主公的杀要直接掉血。

还有伤害来源不是用牌者而是对方。

要判断是跳反还是跳忠。


南猪入侵:出牌阶段,对除你以外所有角色使用,按逆时针顺序从使用者下家开始依次结算,除非弃置一张杀,否则受到1点伤害;

这里判断一下死了就直接跳过,蒟蒻因为这个调了好几天。。。

每个人都要判断。


万箭齐发:和南猪入侵类似,不过要弃置的不是杀而是闪;

做法和题上说的也一样,把杀换成闪就完事了。


还是很麻烦的,最后提醒一下按理来说除了桃使用任意一张手牌后都要重新扫一遍,比如说万箭齐发杀死了你的下家,然后前面的杀有可能就有了目标。

好的现在我们拿到(30)分了。


最后一个最恶心的部分——无懈可击。

orz一下各路用奇偶性来判断的神仙。

蒟蒻只会递归。。。

那么明确一下,无懈可击后,自己和对方的身份都已经暴露了。

判断一下受攻击的人跳没跳身份,如果没跳就直接(return)

记录一个(flag)判断是在献殷勤还是表敌意。

然后暴力枚举判断就行了,找到之后下一层递归要(flag)^=(1)

至此,猪国杀成功(AC)


上代码

#define N 2001001
#define MAX 2001
#define re register
#define inf 1e18
#define eps 1e-10
using namespace std;
typedef long long ll;
typedef double db;
inline void read(re ll &ret)
{
	ret=0;re char c=getchar();re bool pd=false;
	while(!isdigit(c)){pd|=c=='-';c=getchar();}
	while(isdigit(c)){ret=(ret<<1)+(ret<<3)+(c&15);c=getchar();}
	ret=pd?-ret:ret;
	return;
}
ll n,m;
struct zhu
{
	ll paishu,leixing,xueliang;//leixing=1为主猪,2为忠猪,3为反猪 
	char pai[1000001];
	bool zhuge,si,tiaozhong,tiaofan,leifan;
}a[11];
char s[N];
char paidui[2001];
ll head;
inline void print()
{
	for(re int i=1;i<=n;i++)
	{
		if(a[i].si)
			printf("DEAD
");
		else
		{
//			cout<<i<<" "<<a[i].xueliang<<endl;
			for(re int j=1;j<=a[i].paishu;j++)
			{
				if(j>1)
					putchar(' ');
				putchar(a[i].pai[j]);
			}
			putchar('
');
		}
	}
	return;
}
inline void init()
{
	read(n);
	read(m);
	for(re int i=1;i<=n;i++)
	{
		a[i].si=false;
		a[i].xueliang=4;
		a[i].zhuge=false;
		scanf("%s",s+1);
		if(s[1]=='M')
			a[i].leixing=1;
		else if(s[1]=='Z')
			a[i].leixing=2;
		else
			a[i].leixing=3;
		for(re int j=1;j<=4;j++)
		{
			scanf("%s",s+1);
			a[i].pai[++a[i].paishu]=s[1];
		}
	}
	for(re int i=1;i<=m;i++)
	{
		scanf("%s",s+1);
		paidui[i]=s[1];
	}
}
inline void yongpai(re ll num,re ll pos)
{
	for(re int i=pos+1;i<=a[num].paishu;i++)
		a[num].pai[i-1]=a[num].pai[i];
	a[num].paishu--;
	return;
}

inline void jieshu()
{
	re bool mp=true,fp=true;
	for(re int i=1;i<=n;i++)
	{
		if(a[i].xueliang!=0&&a[i].leixing==3)
			mp=false;
		if(a[i].xueliang!=0&&a[i].leixing==1)
			fp=false;
	}
	if(mp)
	{
		printf("MP
");
		print();
		exit(0);
	}
	if(fp)
	{
		printf("FP
");
		print();
		exit(0);
	}
	return;
}
inline void mopai(re ll pos,re ll num)
{
	for(re int i=1;i<=num;i++)
	{
		if(++head>m)
			head=m;
		a[pos].pai[++a[pos].paishu]=paidui[head];
	}
		
	return;
}
inline void si(re ll num,re ll laiyuan)
{
//	cout<<num<<" "<<laiyuan<<endl;
	if(a[num].xueliang>=1)
		return;
	for(re int i=1;i<=a[num].paishu;i++)
	{
		if(a[num].pai[i]=='P')
		{
			yongpai(num,i);
			a[num].xueliang++;
			break;
		}
	}
	if(a[num].xueliang<1)
	{
		a[num].si=true;
		jieshu();
		if(a[num].leixing==3)
			mopai(laiyuan,3);
		else if(a[num].leixing==2&&a[laiyuan].leixing==1)
		{
			a[laiyuan].paishu=0;
			a[laiyuan].zhuge=false;
		}
	}
	return;
}
inline bool shan(re ll pos)
{
	for(re int i=1;i<=a[pos].paishu;i++)
	{
		if(a[pos].pai[i]=='D')
		{
			yongpai(pos,i);
			return true;
		}
	}
	return false;
}
inline bool sha(re ll pos,re ll num)
{
	for(re int i=pos+1;i<=n;i++)
	{
		if(a[i].si)continue;
		if((a[pos].leixing==1&&(a[i].tiaofan||a[i].leifan))||(a[pos].leixing==2&&a[i].tiaofan)||(a[pos].leixing==3&&(a[i].leixing==1||a[i].tiaozhong)))
		{
			yongpai(pos,num);
			if(a[i].tiaofan)
			{
				a[pos].tiaozhong=true;
				a[pos].leifan=false;
			}
			else if(a[i].tiaozhong||a[i].leixing==1)
				a[pos].tiaofan=true;
			if(!shan(i))
			{
				a[i].xueliang--;
				si(i,pos);
			}
			return true;
		}
		return false;	
	}
	for(re int i=1;i<pos;i++)
	{
		if(a[i].si)continue;
		if((a[pos].leixing==1&&(a[i].tiaofan||a[i].leifan))||(a[pos].leixing==2&&a[i].tiaofan)||(a[pos].leixing==3&&(a[i].leixing==1||a[i].tiaozhong)))
		{
			yongpai(pos,num);
			if(a[i].tiaofan)
			{
				a[pos].tiaozhong=true;
				a[pos].leifan=false;
			}
			else if(a[i].tiaozhong||a[i].leixing==1)
				a[pos].tiaofan=true;
			if(!shan(i))
			{
				a[i].xueliang--;
				si(i,pos);
			}
			return true;
		}
		return false;	
	}
}
inline bool wuxie(re ll pos,re ll to,re bool pd)
{
	if(!a[to].tiaofan&&!a[to].tiaozhong&&a[to].leixing!=1)return false;
	if(pd)
	{
		re bool flag=false;
		for(re int i=pos;i<=n;i++)
		{
			if(a[i].si)continue;
			if((a[to].leixing==1&&(a[i].leixing==3))||(a[to].tiaozhong&&(a[i].leixing==3))||(a[to].tiaofan&&(a[i].leixing==1||a[i].leixing==2)))
				continue;
			for(re int j=1;j<=a[i].paishu;j++)
			{
				if(a[i].pai[j]=='J')
				{
					yongpai(i,j);
					if(a[to].leixing==1)
					{
						a[i].tiaozhong=true;
						a[i].leifan=false;
					}
					else if(a[to].leixing==2)
					{
						a[i].tiaozhong=true;
						a[i].leifan=false;
					}
					else
					{
						a[i].tiaofan=true;
						a[i].leifan=false;
					}
				//	if((a[i].leixing==1&&a[pos].leixing==2)||(a[i].leixing==2&&(a[pos].leixing==1||a[pos].leixing==2))||(a[i].leixing==3&&a[pos].leixing==3))
					return !wuxie(i,to,false);
				//	else
				//		return !wuxie(i,to,true);
				}
			}
		}
		for(re int i=1;i<pos;i++)
		{
			if(a[i].si)continue;
			if((a[to].leixing==1&&(a[i].leixing==3))||(a[to].tiaozhong&&(a[i].leixing==3))||(a[to].tiaofan&&(a[i].leixing==1||a[i].leixing==2)))
				continue;
			for(re int j=1;j<=a[i].paishu;j++)
			{
				if(a[i].pai[j]=='J')
				{
					yongpai(i,j);
					if(a[to].leixing==1)
					{
						a[i].tiaozhong=true;
						a[i].leifan=false;
					}
					else if(a[to].leixing==2)
					{
						a[i].tiaozhong=true;
						a[i].leifan=false;
					}
					else
					{
						a[i].tiaofan=true;
						a[i].leifan=false;
					}
			//		if((a[i].leixing==1&&a[pos].leixing==2)||(a[i].leixing==2&&(a[pos].leixing==1||a[pos].leixing==2))||(a[i].leixing==3&&a[pos].leixing==3))
						return !wuxie(i,to,false);
			//		else
			//			return !wuxie(i,to,true);
				}
			}
			
		}
		return false;
	}
	else
	{
		re bool flag=false;
		for(re int i=pos;i<=n;i++)
		{
			if(a[i].si)continue;
			if(!((a[to].leixing==1&&(a[i].leixing==3))||(a[to].tiaozhong&&(a[i].leixing==3))||(a[to].tiaofan&&(a[i].leixing==1||a[i].leixing==2))))
				continue;
			for(re int j=1;j<=a[i].paishu;j++)
			{
				if(a[i].pai[j]=='J')
				{
					yongpai(i,j);
					if(a[to].leixing==1)
					{
						a[i].tiaofan=true;
						a[i].leifan=false;
					}
					else if(a[to].leixing==2)
					{
						a[i].tiaofan=true;
						a[i].leifan=false;
					}
					else
					{
						a[i].tiaozhong=true;
						a[i].leifan=false;
					}
					return !wuxie(i,to,true);
				}
			}
		}
		for(re int i=1;i<pos;i++)
		{
			if(a[i].si)continue;
			if(!((a[to].leixing==1&&(a[i].leixing==3))||(a[to].tiaozhong&&(a[i].leixing==3))||(a[to].tiaofan&&(a[i].leixing==1||a[i].leixing==2))))
				continue;
			for(re int j=1;j<=a[i].paishu;j++)
			{
				if(a[i].pai[j]=='J')
				{
					yongpai(i,j);
					if(a[to].leixing==1)
					{
						a[i].tiaofan=true;
						a[i].leifan=false;
					}
					else if(a[to].leixing==2)
					{
						a[i].tiaofan=true;
						a[i].leifan=false;
					}
					else
					{
						a[i].tiaozhong=true;
						a[i].leifan=false;
					}
					return !wuxie(i,to,true);
				}
			}
			
		}
		return false;
	}
}
inline bool juedou(re ll pos,re ll num)
{
	for(re int i=pos+1;i<=n;i++)
	{
		if(a[i].si)continue;
		if((a[pos].leixing==1&&(a[i].tiaofan||a[i].leifan))||(a[pos].leixing==2&&a[i].tiaofan)||(a[pos].leixing==3&&a[i].leixing==1))
		{
			yongpai(pos,num);
			if(a[i].leixing==3)
			{
				a[pos].tiaozhong=true;
				a[pos].leifan=false;
			}
			else if(a[i].tiaozhong||a[i].leixing==1)
				a[pos].tiaofan=true;
			if(wuxie(pos,i,true))
				return true;
			if(a[pos].leixing==1&&a[i].leixing==2)
			{
				a[i].xueliang--;
				si(i,pos);
				return true;
			}
			re ll turn=i;
			while(true)
			{
				re bool flag=false;
				for(re int j=1;j<=a[turn].paishu;j++)
				{
					if(a[turn].pai[j]=='K')
					{
						yongpai(turn,j);
						flag=true;
						break;
					}
				}
				if(!flag)
				{
					a[turn].xueliang--;
					si(turn,turn==pos?i:pos);
					return true;
				}
				if(turn==i)
					turn=pos;
				else
					turn=i;
			}
		}
	}
	for(re int i=1;i<pos;i++)
	{
		if(a[i].si)continue;
		if((a[pos].leixing==1&&(a[i].tiaofan||a[i].leifan))||(a[pos].leixing==2&&a[i].tiaofan)||(a[pos].leixing==3&&a[i].leixing==1))
		{
			yongpai(pos,num);
			if(a[i].leixing==3)
			{
				a[pos].tiaozhong=true;
				a[pos].leifan=false;
			}
			else if(a[i].tiaozhong||a[i].leixing==1)
				a[pos].tiaofan=true;
			if(wuxie(pos,i,true))
				return true;
			if(a[pos].leixing==1&&a[i].leixing==2)
			{
				a[i].xueliang--;
				si(i,pos);
				return true;
			}
			re ll turn=i;
			while(true)
			{
				re bool flag=false;
				for(re int j=1;j<=a[turn].paishu;j++)
				{
					if(a[turn].pai[j]=='K')
					{
						yongpai(turn,j);
						flag=true;
						break;
					}
				}
				if(!flag)
				{
					a[turn].xueliang--;
					si(turn,turn==pos?i:pos);
					return true;
				}
				if(turn==i)
					turn=pos;
				else
					turn=i;
			}
		}
	}
	return false;
}
inline void nanman(re ll pos,re ll num)
{
//	cout<<pos<<" "<<num<<endl;
	yongpai(pos,num);
	for(re int i=pos+1;i<=n;i++)
	{
		if(a[i].si)continue;
		if(wuxie(pos,i,true))continue;
		re bool flag=false;
		for(re int j=1;j<=a[i].paishu;j++)
		{
			if(a[i].pai[j]=='K')
			{
				yongpai(i,j);
				flag=true;
				break;
			}
		}
		if(!flag)
		{
			a[i].xueliang--;
			if(a[i].leixing==1&&!a[pos].tiaozhong&&!a[pos].tiaofan)
				a[pos].leifan=true;
			si(i,pos);
		}
	}
	for(re int i=1;i<pos;i++)
	{
		if(a[i].si)continue;
		if(wuxie(pos,i,true))continue;
		re bool flag=false;
		for(re int j=1;j<=a[i].paishu;j++)
		{
			if(a[i].pai[j]=='K')
			{
				yongpai(i,j);
				flag=true;
				break;
			}
		}
		if(!flag)
		{
			a[i].xueliang--;
			if(a[i].leixing==1&&!a[pos].tiaozhong&&!a[pos].tiaofan)
				a[pos].leifan=true;
			si(i,pos);
		}
	}
	return;
}
inline void wanjian(re ll pos,re ll num)
{
//	cout<<pos<<" "<<num<<endl;
	yongpai(pos,num);
	for(re int i=pos+1;i<=n;i++)
	{
		if(a[i].si)continue;
		if(wuxie(pos,i,true))continue;
		if(!shan(i))
		{
			a[i].xueliang--;
			if(a[i].leixing==1&&!a[pos].tiaozhong&&!a[pos].tiaofan)
				a[pos].leifan=true;
			si(i,pos);
		}
	}
	for(re int i=1;i<pos;i++)
	{
		if(a[i].si)continue;
		if(wuxie(pos,i,true))continue;
		if(!shan(i))
		{
			a[i].xueliang--;
			if(a[i].leixing==1&&!a[pos].tiaozhong&&!a[pos].tiaofan)
				a[pos].leifan=true;
			si(i,pos);
		}
	}
	return;
}
inline void chupai(re ll pos)
{
	re bool chuguosha=false;
	for(re int i=1;i<=a[pos].paishu;i++)
	{
		if(a[pos].si)
			return;
		if(a[pos].pai[i]=='P')
		{
			if(a[pos].xueliang<4)
			{
				yongpai(pos,i);
				i=0;
				a[pos].xueliang++;
			}
		}
		else if(a[pos].pai[i]=='K'&&(!chuguosha||a[pos].zhuge))
		{
			if(sha(pos,i))
			{
				i=0;
				chuguosha=true;
			}
		}
		else if(a[pos].pai[i]=='F')
		{
			if(juedou(pos,i))
				i=0;
		}
		else if(a[pos].pai[i]=='N')
		{
			nanman(pos,i);
			i=0;
		}
		else if(a[pos].pai[i]=='W')
		{
			wanjian(pos,i);
			i=0;
		}
		else if(a[pos].pai[i]=='Z')
		{
			a[pos].zhuge=true;
			yongpai(pos,i);
			i=0;
		}
	//	cout<<i<<endl;
	}
	return;
}
/*
『桃(P)』
『杀(K)』
『闪(D)』
『决斗(F)』
『南猪入侵(N)』
『万箭齐发(W)』
『无懈可击(J)』
『猪哥连弩(Z)』
*/
inline void work()
{
	re ll num=0;
	while(true)
	{
		num%=n;
		num++;
		if(a[num].si)
			continue;
		mopai(num,2);
		chupai(num);
	}
}
signed main()
{
	init();
	work();
	exit(0);
}
//[SDOI2010]猪国杀
原文地址:https://www.cnblogs.com/CelticBlog/p/13531627.html