首页 > 其他分享 >【题解】Luogu-P2482 SDOI2010 猪国杀

【题解】Luogu-P2482 SDOI2010 猪国杀

时间:2023-09-02 16:00:35浏览次数:38  
标签:猪国 int 题解 Number SDOI2010 Player bool inline Card

写了 \(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;
}

标签:猪国,int,题解,Number,SDOI2010,Player,bool,inline,Card
From: https://www.cnblogs.com/SoyTony/p/Solution_on_Luogu-P2482.html

相关文章

  • CF1863C 题解
    CF1863CMEXRepetition题解Links洛谷CodeforcesDescription给你一个长度为\(n\)的序列\(a\),满足\(\foralli\in[1,n]\),\(0\leqa_{i}\leqn\)且序列中的数互不相同。定义一次操作为:按照\(i\)从\(1\)到\(n\)的顺序,\(a_{i}\gets\operatorname{MEX}(a_{1}......
  • CF1863B 题解
    CF1863BSplitSort题解Links洛谷CodeforcesDescription给定一个\(1\simn\)的排列\(q\),你可以多次进行以下操作:新建一个初始为空的序列\(q\);选择一个整数\(x\)(\(2\leqx\leqn\));按照在\(p\)中出现的顺序将所有小于\(x\)的数添加到序列\(q\)末尾。按照在......
  • P1463 [POI2001] [HAOI2007] 反素数 题解
    P1463[POI2001][HAOI2007]反素数题解可以发现,最大的不超过\(n\)的反素数就是\(1\simn\)中因数最多的数字。证明:设\(x,x\in[1,n]\)为\(1\simn\)中因数最多的数字,则\(x<y\len\)都不会成为答案,因为存在\(x<y\)因数比\(y\)多,同时也不会存在\(y'<x\)......
  • vmware中的疑难问题解决方法
    converter在windows中使用的agent服务端口9089,vcenter使用443端口。converter再windows中不能启动服务的解决方法:1.开启TLS1.01.11.2。在programdata中更改SSLOPTIONS的值为:56313856。可以尝试官方方法2.禁用网络连接:在注册表中localmachine-system-currentcontrolset-contro......
  • CF 1863D 题解
    CF1863DTwo-ColoredDominoes题解Links洛谷CodeforcesDescription有一个\(n\timesm\)的棋盘,上面铺着一些\(1\times2\)的多米诺骨牌(横竖均有可能),骨牌之间没有重叠。你需要找到一种染色方案满足以下条件:每个多米诺骨牌一端被染白,另一端被染黑。其他没有骨牌的格子......
  • 题解 [AGC004D] Teleporter
    题目链接躺在床上想到重要性质的题目。。。首先,由于每个城市只有一个可以直接到达的城市,所以\(n\)个城市就有\(n\)条边,容易发现这是一棵基环树,那么我们先从普通树的角度考虑,若要求每个点走\(k\)条边恰好到\(1\)号节点,这个环必须加在哪里。若\(k=1\),没有环显然也是可行......
  • GCD Counting题解
    题意有一棵有\(n\)个节点的树,第\(i\)个节点有点权\(a_i\)。定义\(g(x,y)\)为\(x\)到\(y\)的树上路径所经过的点的点权\(\gcd\)。对于每一个正整数\(k\in[1,2\times10^5]\)求出满足以下条件的\(x,y\)的对数:\(1\lex\ley\len\)\(g(x,y)=k\)\(1\len......
  • CF915G Coprime Arrays 题解
    题意给定\(n,k\),对于所有的\(m\in\left[1,k\right]\),求长度为\(n\),值域为\(\left[1,m\right]\)且最大公约数为\(1\)的序列种数,对\(10^9+7\)取模。(\(1\len,k\le2\times10^6\))。题解设\(f(d,m)\)表示长度为\(n\),值域为\(\left[1,m\right]\)且最大......
  • [NOI2021] 轻重边题解
    题目传送门一眼数据结构考虑树上有什么数据结构支持\(x\)到\(y\)节点的修改和查询,那就是:树链剖分。那么这道树链剖分的题有个\(trick\):边点转换&染色法,对于每次修改,考虑将修改路径上的点全部染上一种独一无二的颜色,而查询的时候,就查询路径上相邻的相同的颜色节点个数即可......
  • 爱思创模拟06试题易错题解析
    错误原因:漏项正确答案:C按节点数分类穷举 举一反三:  错误原因:处理三个空位的时候,情况考虑的太多正确答案:分情况计算,先枚举4个人共A(4,4)=24种情况,再考虑剩下两个空位置的情况,即A(5,2)=20种情况,最终答案就是24*20=480种举一反三:  错误原因:不会计算时间复杂度......