题解 洛谷P2482 【[SDOI2010]猪国杀】

概述

题号 难度 \(AC\)时间及记录
\(\texttt{洛谷P2482}\) \(\texttt{洛谷难度:省选/NOI-}\) \(\texttt{On 2021/02/15}\)

解析

导语部分

这是一道传说级别的题目。

最近状态不好,只好逼自己刷一道大型模拟题。
那么言归正传,我们先得梳理一下题目大意。

题目大意

\(\mathcal{FOCAL\ POINT1}\)

主猪\(\texttt{MP}\):自己存活的情况下消灭所有的反猪。
忠猪\(\texttt{ZP}\):不惜一切保护主猪,胜利条件与主猪相同。
反猪\(\texttt{FP}\):杀死主猪。

\(\mathcal{FOCAL\ POINT2}\)

『桃\(\texttt{P}\)』在自己的回合内,如果自己的体力值不等于体力上限,那么使用\(1\)个桃可以为自己补充\(1\)点体力,否则不能使用桃;桃只能对自己使用;在自己的回合外,如果自己的血变为\(0\)或者更低,那么也可以使用。
『杀\(\texttt{K}\)』在自己的回合内,对攻击范围内除自己以外的\(1\)名角色使用。如果没有被『闪』抵消,则造成\(1\)点伤害。无论有无武器,杀的攻击范围都是\(1\)
『闪\(\texttt{D}\)』当你受到杀的攻击时,可以弃置\(1\)张闪来抵消杀的效果。

\(\mathcal{FOCAL\ POINT3}\)

游戏开始时,每个玩家手里都会有\(4\)张牌,且体力上限和初始体力都是\(4\)
开始游戏时,从主猪开始,按照逆时针方向(数据中就是按照编号从\(1,2,3\ldots n,1\ldots\) 的顺序)依次行动。
每个玩家自己的回合可以分为\(2\)个阶段:

  • 摸牌阶段:从牌堆顶部摸\(2\)张牌,依次放到手牌的最右边;
  • 出牌阶段:你可以使用任意张牌,每次使用牌的时候都使用最靠左的能够使用的牌。当然,要满足如下规则:
    如果没有猪哥连弩,每个出牌阶段只能使用\(1\)次「杀」来攻击;
    任何牌被使用后被弃置(武器是装备上);被弃置的牌以后都不能再用,即与游戏无关。

\(\mathcal{FOCAL\ POINT4}\)

『决斗\(\texttt{F}\)』出牌阶段,对除自己以外任意\(1\)名角色使用,由目标角色先开始,自己和目标角色轮流弃置\(1\)张杀,首先没有杀可弃的一方受到\(1\)点伤害,另一方视为此伤害的来源。
『南猪入侵\(\texttt{N}\)』出牌阶段,对除你以外所有角色使用,按逆时针顺序从使用者下家开始依次结算,除非弃置\(1\)张杀,否则受到\(1\)点伤害。
『万箭齐发\(\texttt{W}\)』和南猪入侵类似,不过要弃置的不是杀而是闪。
『无懈可击\(\texttt{J}\)』在目标锦囊生效前抵消其效果。每次有\(1\)张锦囊即将生效时,从使用这张锦囊的猪开始,按照逆时针顺序,依次得到使用无懈可击的机会;效果:用于决斗时,决斗无效并弃置;用于南猪入侵或万箭齐发时,当结算到某个角色时才能使用,当前角色不需弃置牌并且不会受到伤害(仅对\(1\)个角色产生效果);用于无懈可击时,成为目标的无懈可击被无效。
『猪哥连弩\(\texttt{Z}\)』武器,攻击范围\(1\),出牌阶段你可以使用任意张杀; 同一时刻最多只能装\(1\)把武器;如果先前已经有了\(1\)把武器,那么之后再装武器的话,会弃置以前的武器来装现在的武器。

\(\mathcal{FOCAL\ POINT5}\)

\(\huge\ldots\ldots\)
详见这里

解法剖析

见代码\(\ldots\)

做题悲惨经历

代码

#include<bits/stdc++.h>
using namespace std;
struct Struct
{
	string Identity;
	string S[2001];
	int CardSize;
	int Hp;
	int Prev;
	int Next;
	bool LianFa;
};
int TotalPlayer,TotalBrand;
Struct Player[11];
string BrandOfPublic[2001];
char Zg[11];
int FpSl;
int Alive;
bool GameOver;
inline void vDie(int X1,int X2);
inline void vSha(int X1,int X2);
inline bool vWuXieKeJi(int X1,int X2,int X3);
inline void vNanManRuQin(int X);
inline void vWanJianQiFa(int X);
inline void vJueDou(int X1,int X2);
inline void vZhuGe(int X);
inline void vGetCards(int X);
inline void vInput();
inline void vWork();
inline void vOutput();
int main(void)
{
	vInput();
	vWork();
	vOutput();
	return 0;
}
inline void vDie(int X1,int X2)
{
	register int i;
	for(i=1;i<=Player[X2].CardSize;i++)
	{
		if(Player[X2].S[i]=="P")
		{
			Player[X2].S[i]="G";
			Player[X2].Hp++;
			return;
		}
	}
	Player[Player[X2].Next].Prev=Player[X2].Prev;
	Player[Player[X2].Prev].Next=Player[X2].Next;
	if(X2==1)
	{
		GameOver=true;
		return;
	}
	if(Player[X2].Identity[0]=='F')
	{
		FpSl--;
	}
	if(!FpSl)
	{
		GameOver=true;
		return;
	}
	if(Player[X2].Identity[0]=='F')
	{
		vGetCards(X1);
		vGetCards(X1);
		vGetCards(X1);
	}
	if(Player[X2].Identity[0]=='Z'&&Player[X1].Identity[0]=='M')
	{
		Player[X1].CardSize=0;
		Player[X1].LianFa=false;
	}
}
inline void vSha(int X1,int X2)
{
	register int i;
	for(i=1;i<=Player[X2].CardSize;i++)
	{
		if(Player[X2].S[i]=="D")
		{
			Player[X2].S[i]="G";
			return;
		}
	}
	Player[X2].Hp--;
	if(!Player[X2].Hp)
	{
		vDie(X1,X2);
	}
}
inline bool vWuXieKeJi(int X1,int X2,int X3)
{
	register int i;
	i=X1;
	while(true)
	{
		if(X3)
		{
			if((Zg[X2]==Player[i].Identity[0]||(Zg[X2]=='M'&&Player[i].Identity[0]=='Z'))||(Zg[X2]=='Z'&&Player[i].Identity[0]=='M'))
			{
				register int j;
				for(j=1;j<=Player[i].CardSize;j++)
				{
					if(Player[i].S[j]=="J")
					{
						Player[i].S[j]='G';
						Zg[i]=Player[i].Identity[0];
						return !vWuXieKeJi(i,X1,0);
					}
				}
			}
		}
		else
		{
			if(((Player[i].Identity[0]=='M'||Player[i].Identity[0]=='Z')&&Zg[X1]=='F')||(Player[i].Identity[0]=='F'&&(Zg[X1]=='M'||Zg[X1]=='Z')))
			{
				register int j;
				for(j=1;j<=Player[i].CardSize;j++)
				{
					if(Player[i].S[j]=="J")
					{
						Player[i].S[j]="G";
						Zg[i]=Player[i].Identity[0];
						return !vWuXieKeJi(i,X1,0);
					}
				}
			}
		}
		i=Player[i].Next;
		if(i==X1)
		{
			break;
		}
	}
	return false;
}
inline void vNanManRuQin(int X)
{
	register int i;
	for(i=Player[X].Next;i!=X;i=Player[i].Next)
	{
		if(!vWuXieKeJi(X,i,1))
		{
			register int j;
			for(j=1;j<=Player[i].CardSize;j++)
			{
				if(Player[i].S[j]=="K")
				{
					Player[i].S[j]="G";
					break;
				}
			}
			if(j>Player[i].CardSize)
			{
				Player[i].Hp--;
				if(i==1&&Zg[X]=='G')
				{
					Zg[X]='L';
				}
				if(!Player[i].Hp)
				{
					vDie(X,i);
				}
				if(GameOver)
				{
					return;
				}
			}
		}
	}
}
inline void vWanJianQiFa(int X)
{
	register int i;
	for(i=Player[X].Next;i!=X;i=Player[i].Next)
	{
		if(!vWuXieKeJi(X,i,1))
		{
			register int j;
			for(j=1;j<=Player[i].CardSize;j++)
			{
				if(Player[i].S[j]=="D")
				{
					Player[i].S[j]="G";
					break;
				}
			}
			if(j>Player[i].CardSize)
			{
				Player[i].Hp--;
				if(i==1&&Zg[X]=='G')
				{
					Zg[X]='L';
				}
				if(!Player[i].Hp)
				{
					vDie(X,i);
				}
				if(GameOver)
				{
					return;
				}
			}
		}
	}
}
inline void vJueDou(int X1,int X2)
{
	register int j,k;
	if(vWuXieKeJi(X1,X2,1))
	{
		return;
	}
	if(X1==1&&Player[X2].Identity[0]=='Z')
	{
		Player[X2].Hp--;
		if(!Player[X2].Hp)
		{
			vDie(X1,X2);
		}
		return;
	}
	j=k=1;
	while(true)
	{
		while(Player[X2].S[j]!="K"&&j<=Player[X2].CardSize)
		{
			j++;
		}
		if(j>Player[X2].CardSize)
		{
			Player[X2].Hp--;
			if(!Player[X2].Hp)
			{
				vDie(X1,X2);
			}
			return;
		}
		else
		{
			Player[X2].S[j]="G";
		}
		while(Player[X1].S[k]!="K"&&k<=Player[X1].CardSize)
		{
			k++;
		}
		if(k>Player[X1].CardSize)
		{
			Player[X1].Hp--;
			if(!Player[X1].Hp)
			{
				vDie(X2,X1);
			}
			return;
		}
		else
		{
			Player[X1].S[k]="G";
		}
	}
}
inline void vZhuGe(int X)
{
	Player[X].LianFa=true;
}
inline void vGetCards(int X)
{
	if(!TotalBrand)
	{
		TotalBrand=1;
	}
	Player[X].S[++Player[X].CardSize]=BrandOfPublic[TotalBrand];
	TotalBrand--;
}
inline void vInput()
{
	register int i,j;
	cin>>TotalPlayer>>TotalBrand;
	for(i=1;i<=TotalPlayer;i++)
	{
		Player[i].Next=i+1;
		Player[i].Prev=i-1; 
		for(j=1;j<=2000;j++)
		{
			Player[i].S[j]="G";
		}
	}
	Player[TotalPlayer].Next=1; 
	Player[1].Prev=TotalPlayer; 
	for(i=1;i<=TotalPlayer;i++)
	{
		cin>>Player[i].Identity;
		for(j=1;j<=4;j++)
		{
			cin>>Player[i].S[j];
		}
		Player[i].CardSize=4;
		Player[i].Hp=4;
		if(Player[i].Identity=="FP")
		{
			FpSl++;
		}
		Player[i].LianFa=false;
	}
	Zg[1]='M';
	for(i=2;i<=TotalPlayer;i++)
	{
		Zg[i]='G';
	}
	for(i=1;i<=TotalBrand;i++)
	{
		register string sNow;
		cin>>sNow;
		BrandOfPublic[TotalBrand-i+1]=sNow[0];
	}
}
inline void vWork()
{
	register int i,j,k;
	Alive=TotalPlayer;
	register string NowCard;
	if(FpSl)
	{
		GameOver=false;
	}
	if(GameOver)
	{
		return;
	}
	for(i=1;i;i=Player[i].Next)
	{
		vGetCards(i);
		vGetCards(i);
		register bool Kill;
		Kill=true;
		for(j=1;j<=Player[i].CardSize;j++)
		{
			if(Player[i].S[j]!="G")
			{
				if(!Player[i].Hp)
				{
					break;
				}
				NowCard=Player[i].S[j];
				if(NowCard=="P")
				{
					if(Player[i].Hp!=4)
					{
						Player[i].Hp++;
						Player[i].S[j]="G";
						continue;
					}
				}
				if(NowCard=="K")
				{
					if(!Kill&&!Player[i].LianFa)
					{
						continue;
					}
					if(Player[i].Identity=="MP"&&Zg[Player[i].Next]!='L'&&Zg[Player[i].Next]!='F')
					{
						continue;
					}
					if(Player[i].Identity=="ZP"&&Zg[Player[i].Next]!='F')
					{
						continue;
					}
					if(Player[i].Identity=="FP"&&Zg[Player[i].Next]!='Z'&&Zg[Player[i].Next]!='M')
					{
						continue;
					}
					Player[i].S[j]="G";
					vSha(i,Player[i].Next);
					Zg[i]=Player[i].Identity[0];
					Kill=false;
					if(GameOver)
					{
						return;
					}
					continue;
				}
				if(NowCard=="F")
				{
					if(Player[i].Identity[0]=='F')
					{
						Player[i].S[j]="G";
						vJueDou(i,1);
						Zg[i]=Player[i].Identity[0];
						if(GameOver)
						{
							return;
						}
						j=0;
						continue;
					}
					for(k=Player[i].Next;k!=i;k=Player[k].Next)
					{
						if((Player[i].Identity[0]=='M'&&(Zg[k]=='L'||Zg[k]=='F'))||(Player[i].Identity[0]=='Z'&&Zg[k]=='F'))
						{
							Player[i].S[j]="G";
							vJueDou(i,k);
							Zg[i]=Player[i].Identity[0];
							if(GameOver)
							{
								return;
							}
							j=0;
							break;
						}
					}
					continue;
				}
				if(NowCard=="N")
				{
					Player[i].S[j]="G";
					vNanManRuQin(i);
					if(GameOver)
					{
						return;
					}
					j=0;
					continue;
				}
				if(NowCard=="W")
				{
					Player[i].S[j]="G";
					vWanJianQiFa(i);
					if(GameOver)
					{
						return;
					}
					j=0;
					continue;
				}
				if(NowCard=="Z")
				{
					vZhuGe(i);
					Player[i].S[j]="G";
					j=0;
					continue;
				}
			}
		}
	}
}
inline void vOutput()
{
	register int i,j;
	if(Player[1].Hp<=0)
	{
		cout<<"FP"<<endl;
	}
	else
	{
		cout<<"MP"<<endl;
	}
	for(i=1;i<=TotalPlayer;i++)
	{
		if(Player[i].Hp<=0)
		{
			cout<<"DEAD"<<endl;
		}
		else
		{
			for(j=1;j<=Player[i].CardSize;j++)
			{
				if(Player[i].S[j]!="G")
				{
					cout<<Player[i].S[j]<<' ';
				}
			}
			cout<<endl;
		}
	}
}
posted @ 2021-02-15 22:08  Bushuai_Tang  阅读(166)  评论(0)    收藏  举报