题解 洛谷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;
}
}
}
浙公网安备 33010602011771号