1. 程式人生 > 實用技巧 >題解 [SDOI2010]豬國殺

題解 [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\n");
		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('\n');
		}
	}
	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\n");
		print();
		exit(0);
	}
	if(fp)
	{
		printf("FP\n");
		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]豬國殺