【题解】Luogu-P2482 SDOI 2010 猪国杀
写了 \(358\) 行,\(11.94 \mathrm{KB}\),有这么几个地方写挂了:
-
反猪决斗一定选主猪。
-
游戏结束判定是主猪死亡或全部反猪死亡。
-
决斗可能被反杀,之后不能再出牌。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
int n,m;
char Ch[3];
queue<char> Deck;
int Count_Identities[4];
int Count_Players;
int Previous_Player[11],Next_Player[11];
inline void Erase_Player(int Player_Number){
Next_Player[Previous_Player[Player_Number]]=Next_Player[Player_Number];
Previous_Player[Next_Player[Player_Number]]=Previous_Player[Player_Number];
--Count_Players;
}
struct PLAYER{
int Identity,Current_Identity;
int HP;
bool Dead;
int Card_Queue_Head,Card_Queue_Tail,Count_Cards;
int Previous_Card[2005],Next_Card[2005];
char Card_Type[2005];
bool K_Played,Z_Played;
inline void Input();
inline void Get_Card();
inline void Erase_Card(int Card_Number);
inline void Check_Dead(int Player_Number,int Source_Player_Number);
inline void Output_Cards();
inline bool P_Play(int Card_Number);
inline bool K(int Player_Number,int Card_Number);
inline bool K_Play();
inline bool D_Play();
inline bool F_Check(int Player_Number,int Card_Number);
inline void F_Play(int Player_Number,int Source_Player_Number);
inline bool N(int Player_Number,int Card_Number);
inline bool W(int Player_Number,int Card_Number);
inline int J_Check(int Player_Number,int Source_Player_Number,bool Type);
inline bool J_Play(int Player_Number);
inline bool Z(int Player_Number);
inline void Play(int Player_Number);
}Player[11];
inline void PLAYER::Input(){
scanf("%s",Ch);
if(Ch[0]=='M') Identity=1;
else if(Ch[0]=='Z') Identity=2;
else Identity=3;
++Count_Identities[Identity];
Current_Identity=0;
HP=4;
Dead=false;
Card_Queue_Head=1,Card_Queue_Tail=4,Count_Cards=4;
for(int i=1;i<=4;++i){
scanf("%s",Ch);
Previous_Card[i]=i-1,Next_Card[i]=i+1;
Card_Type[i]=Ch[0];
}
Previous_Card[1]=-1,Next_Card[4]=-1;
K_Played=false,Z_Played=false;
}
inline void PLAYER::Get_Card(){
++Count_Cards;
Card_Type[Count_Cards]=Deck.front();
Previous_Card[Count_Cards]=Card_Queue_Tail,Next_Card[Count_Cards]=-1;
if(Card_Queue_Tail!=-1) Next_Card[Card_Queue_Tail]=Count_Cards;
else Card_Queue_Head=Count_Cards;
Card_Queue_Tail=Count_Cards;
if((int)Deck.size()>1) Deck.pop();
}
inline void PLAYER::Erase_Card(int Card_Number){
if(Card_Number==Card_Queue_Head) Card_Queue_Head=Next_Card[Card_Number];
else Next_Card[Previous_Card[Card_Number]]=Next_Card[Card_Number];
if(Card_Number==Card_Queue_Tail) Card_Queue_Tail=Previous_Card[Card_Number];
else Previous_Card[Next_Card[Card_Number]]=Previous_Card[Card_Number];
}
inline void PLAYER::Check_Dead(int Player_Number,int Source_Player_Number){
--HP;
if(HP) return;
for(int i=Card_Queue_Head;i!=-1;i=Next_Card[i]){
if(Card_Type[i]!='P') continue;
P_Play(i);
return;
}
Dead=true;
--Count_Identities[Identity];
Erase_Player(Player_Number);
if(!Count_Identities[3]){
printf("MP\n");
for(int i=1;i<=n;++i){
if(Player[i].Dead) printf("DEAD\n");
else Player[i].Output_Cards();
}
exit(0);
}
else if(!Count_Identities[1]){
printf("FP\n");
for(int i=1;i<=n;++i){
if(Player[i].Dead) printf("DEAD\n");
else Player[i].Output_Cards();
}
exit(0);
}
if(Identity==3){
Player[Source_Player_Number].Get_Card(),Player[Source_Player_Number].Get_Card(),Player[Source_Player_Number].Get_Card();
}
else if(Player[Source_Player_Number].Identity==1&&Identity==2){
Player[Source_Player_Number].Card_Queue_Head=Player[Source_Player_Number].Card_Queue_Tail=-1;
Player[Source_Player_Number].Z_Played=false;
}
}
inline void PLAYER::Output_Cards(){
for(int i=Card_Queue_Head;i!=-1;i=Next_Card[i]) printf("%c ",Card_Type[i]);
printf("\n");
}
inline bool PLAYER::P_Play(int Card_Number){
if(HP<4){
++HP;
Erase_Card(Card_Number);
return true;
}
else return false;
}
inline bool PLAYER::K(int Player_Number,int Card_Number){
if(K_Played&&!Z_Played) return false;
if(Identity==1&&(Player[Next_Player[Player_Number]].Current_Identity==2||Player[Next_Player[Player_Number]].Current_Identity==3)){
Erase_Card(Card_Number);
bool D_Played=Player[Next_Player[Player_Number]].D_Play();
if(!D_Played) Player[Next_Player[Player_Number]].Check_Dead(Next_Player[Player_Number],Player_Number);
}
else if(Identity==2&&Player[Next_Player[Player_Number]].Current_Identity==2){
Erase_Card(Card_Number);
bool D_Played=Player[Next_Player[Player_Number]].D_Play();
if(!D_Played) Player[Next_Player[Player_Number]].Check_Dead(Next_Player[Player_Number],Player_Number);
Current_Identity=1;
}
else if(Identity==3&&(Player[Next_Player[Player_Number]].Identity==1||Player[Next_Player[Player_Number]].Current_Identity==1)){
Erase_Card(Card_Number);
bool D_Played=Player[Next_Player[Player_Number]].D_Play();
if(!D_Played) Player[Next_Player[Player_Number]].Check_Dead(Next_Player[Player_Number],Player_Number);
Current_Identity=2;
}
else return false;
K_Played=true;
return true;
}
inline bool PLAYER::K_Play(){
for(int i=Card_Queue_Head;i!=-1;i=Next_Card[i]){
if(Card_Type[i]!='K') continue;
Erase_Card(i);
return true;
}
return false;
}
inline bool PLAYER::D_Play(){
for(int i=Card_Queue_Head;i!=-1;i=Next_Card[i]){
if(Card_Type[i]!='D') continue;
Erase_Card(i);
return true;
}
return false;
}
inline bool PLAYER::F_Check(int Player_Number,int Card_Number){
if(Identity!=3){
for(int i=Next_Player[Player_Number];i!=Player_Number;i=Next_Player[i]){
if(
(Identity==1&&(Player[i].Current_Identity==2||Player[i].Current_Identity==3))||
(Identity==2&&Player[i].Current_Identity==2)){
Current_Identity=1;
Erase_Card(Card_Number);
F_Play(i,Player_Number);
return true;
}
}
}
else{
Current_Identity=2;
Erase_Card(Card_Number);
F_Play(1,Player_Number);
return true;
}
return false;
}
inline void PLAYER::F_Play(int Player_Number,int Source_Player_Number){
bool Type=false;
int Temporary_Source_Player_Number=Source_Player_Number;
while(1){
int J_Played=Player[Player_Number].J_Check(Player_Number,Source_Player_Number,Type);
if(!J_Played) break;
Source_Player_Number=J_Played,Type^=1;
}
if(Type) return;
Source_Player_Number=Temporary_Source_Player_Number;
bool Turn=false;
while(1){
if(!Turn){
bool FK_Played;
if(Identity==1&&Player[Player_Number].Identity==2) FK_Played=false;
else FK_Played=Player[Player_Number].K_Play();
if(!FK_Played){
Player[Player_Number].Check_Dead(Player_Number,Source_Player_Number);
return;
}
}
else{
bool FK_Played;
if(Player[Player_Number].Identity==1&&Identity==2) FK_Played=false;
else FK_Played=K_Play();
if(!FK_Played){
Check_Dead(Source_Player_Number,Player_Number);
return;
}
}
Turn^=1;
}
}
inline bool PLAYER::N(int Player_Number,int Card_Number){
Erase_Card(Card_Number);
int Source_Player_Number;
for(int i=Next_Player[Player_Number];i!=Player_Number;i=Next_Player[i]){
bool Type=false;
Source_Player_Number=Player_Number;
while(1){
int J_Played=Player[i].J_Check(i,Source_Player_Number,Type);
if(!J_Played) break;
Source_Player_Number=J_Played,Type^=1;
}
if(Type) continue;
Source_Player_Number=Player_Number;
bool NK_Played=Player[i].K_Play();
if(!NK_Played){
if(Player[i].Identity==1&&!Current_Identity) Current_Identity=3;
Player[i].Check_Dead(i,Source_Player_Number);
}
}
return true;
}
inline bool PLAYER::W(int Player_Number,int Card_Number){
Erase_Card(Card_Number);
int Source_Player_Number;
for(int i=Next_Player[Player_Number];i!=Player_Number;i=Next_Player[i]){
bool Type=false;
Source_Player_Number=Player_Number;
while(1){
int J_Played=Player[i].J_Check(i,Source_Player_Number,Type);
if(!J_Played) break;
Source_Player_Number=J_Played,Type^=1;
}
if(Type) continue;
Source_Player_Number=Player_Number;
bool WD_Played=Player[i].D_Play();
if(!WD_Played){
if(Player[i].Identity==1&&!Current_Identity) Current_Identity=3;
Player[i].Check_Dead(i,Source_Player_Number);
}
}
return true;
}
inline int PLAYER::J_Check(int Player_Number,int Source_Player_Number,bool Type){
if(Identity!=1&&Current_Identity!=1&&Current_Identity!=2) return 0;
bool Source_Player_Visited=false;
for(int i=Source_Player_Number;;i=Next_Player[i]){
if(i==Source_Player_Number){
if(Source_Player_Visited) return 0;
else Source_Player_Visited=true;
}
if(!Type){
if(
(Identity==1&&(Player[i].Identity==1||Player[i].Identity==2))||
(Current_Identity==1&&(Player[i].Identity==1||Player[i].Identity==2))){
bool J_Played=Player[i].J_Play(i);
if(J_Played){
Player[i].Current_Identity=1;
return i;
}
}
else if(Current_Identity==2&&Player[i].Identity==3){
bool J_Played=Player[i].J_Play(i);
if(J_Played){
Player[i].Current_Identity=2;
return i;
}
}
}
else{
if(
(Identity==1&&Player[i].Identity==3)||
(Current_Identity==1&&Player[i].Identity==3)){
bool J_Played=Player[i].J_Play(i);
if(J_Played){
Player[i].Current_Identity=2;
return i;
}
}
else if(
(Current_Identity==2&&(Player[i].Identity==1||Player[i].Identity==2))||
(Current_Identity==3&&Player[i].Identity==1)){
bool J_Played=Player[i].J_Play(i);
if(J_Played){
Player[i].Current_Identity=1;
return i;
}
}
}
}
}
inline bool PLAYER::J_Play(int Player_Number){
for(int i=Card_Queue_Head;i!=-1;i=Next_Card[i]){
if(Card_Type[i]!='J') continue;
Erase_Card(i);
return true;
}
return false;
}
inline bool PLAYER::Z(int Card_Number){
Z_Played=true;
Erase_Card(Card_Number);
return true;
}
inline void PLAYER::Play(int Player_Number){
Get_Card(),Get_Card();
K_Played=false;
while(1){
bool Played=false;
for(int i=Card_Queue_Head;i!=-1;i=Next_Card[i]){
if(Card_Type[i]=='P') Played=P_Play(i);
else if(Card_Type[i]=='K') Played=K(Player_Number,i);
else if(Card_Type[i]=='F') Played=F_Check(Player_Number,i);
else if(Card_Type[i]=='N') Played=N(Player_Number,i);
else if(Card_Type[i]=='W') Played=W(Player_Number,i);
else if(Card_Type[i]=='Z') Played=Z(i);
else continue;
if(Played) break;
}
if(Dead) break;
if(!Played) break;
}
}
int main(){
scanf("%d%d",&n,&m);
Count_Players=n;
for(int i=1;i<=n;++i) Player[i].Input();
for(int i=1;i<=m;++i){
scanf("%s",Ch);
Deck.push(Ch[0]);
}
for(int i=1;i<=n;++i) Previous_Player[i]=i-1,Next_Player[i]=i+1;
Previous_Player[1]=n,Next_Player[n]=1;
int Current_Player=1;
while(1){
Player[Current_Player].Play(Current_Player);
Current_Player=Next_Player[Current_Player];
}
return 0;
}