[SDOI2010]猪国杀 题解

[SDOI2010]猪国杀 题解

Problem

​ 见原题面

Solution

​ 大模拟,前后共花了一天多一点写完,点几个需要注意的细节:

​ 1.注意献殷勤和表敌意在出无懈可击时的差异,具体见代码

​ 2.注意AOE伤害中途游戏结束不会继续结算这个AOE伤害

​ 3.注意反猪有决斗的话必先对主猪使用

​ 4.注意打出无懈可击的顺序,必须沿逆时针模拟

Code

#include<bits/stdc++.h>
using namespace std;

int n,m;

class Cards{ 

    public:

        char GetCard(){
            return tot==m?P[m]:P[tot++];
        }

        bool IsCard(char c){
            return c=='P'||c=='K'||c=='D'||c=='F'||c=='N'||c=='W'||c=='J'||c=='Z';
        }

        void Initialize(){
            tot=1;
            for(register int i=1;i<=m;++i){
                char ch=getchar();
                while(!IsCard(ch))
                    ch=getchar();
                P[i]=ch;
            }
        }

    private:

        int tot;
        char P[2005];

}H;

class Pig{

    public:

        int GetId(){
            return Id;
        }

        int HPNow(){
            return HP;
        }

        int CardNum(){
            return C.size();
        }

        int Relation(int i){
            return I[i-1];
        }

        char FindCard(int i){
            return C[i];
        }

        bool IsDead(){
            return Dead;
        }

        bool IsEquip(){
            return Crossbow;
        }

        bool Have(char c){
            for(register int i=0;i<C.size();++i){
                if(C[i]==c)
                    return 1;
            }
            return 0;
        }

        bool IsCard(char c){
            return c=='P'||c=='K'||c=='D'||c=='F'||c=='N'||c=='W'||c=='J'||c=='Z';
        }

        void Hurt(){
            if(!--HP){
                if(Have('P')){
                    HP=1;
                    Delt('P');
                }
                else
                    Dead=1;
            }
        }

        void Equip(){
            Crossbow=1;
        }

        void Print(){
            for(register int i=0;i<C.size();++i){
                putchar(C[i]);
                putchar(' ');
            }
        }

        void Discard(){
            C.clear();
            Crossbow=0;
        }

        void Recover(){
            ++HP;
        }

        void Delt(char c){
            vector<char>::iterator IT;
            for(IT=C.begin();IT!=C.end();++IT){
                if(*IT==c){
                    C.erase(IT);
                    break;
                }
            }
        }

        void Getcards(int i){
            while(i--)
                C.push_back(H.GetCard());
        }

        void SetId(int i,int k){
            I[i-1]=k;
        }

        void Initialize(int Now){
            HP=4;Pos=Now;
            char s[2];scanf("%s",s);
            if(s[0]=='M')
                Id=0;
            if(s[0]=='F')
                Id=-1;
            if(s[0]=='Z')
                Id=+1;
            for(register int i=1;i<=4;++i){
                char ch=getchar();
                while(!IsCard(ch))
                    ch=getchar();
                C.push_back(ch);
            }
            for(register int i=1;i<=n;++i)
                I.push_back(0);
        }

    private:

        int HP;                     //当前血量
        int Id;                     //自身身份
        int Pos;                    //自身位置
        bool Dead;                  //是否死亡
        bool Crossbow;              //诸葛连弩
        vector<int >I;              //他人身份
        vector<char>C;              //当前手牌

}P[15];

int Find(int K,int T,int flag){
    int Pos=0;
    for(register int i=K;i<=n;++i){
        if(Pos)
            break;
        if(!P[i].IsDead()&&((flag==1&&P[i].Relation(K)==-1)||(flag!=1&&P[i].Relation(T)==+1))&&P[i].Have('J')){
            Pos=i;
            break;
        }
    }
    for(register int i=1;i< K;++i){
        if(Pos)
            break;
        if(!P[i].IsDead()&&((flag==1&&P[i].Relation(K)==-1)||(flag!=1&&P[i].Relation(T)==+1))&&P[i].Have('J')){
            Pos=i;
            break;
        }       
    }
    return Pos;
}

void ResetId(int K,int T,int op){
    for(register int i=1;i<=n;++i){
        if(i==K)
            P[i].SetId(i,1);
        if(i!=K){
            if(!P[i].Relation(K))
                P[i].SetId(K,op*P[i].Relation(T));
            if(!P[i].GetId()&&P[i].Relation(K)!=+1)
                P[i].SetId(K,op*P[i].Relation(T));
        }
    }   
    return;
}

bool Offset(int From,int To,int flag){
    int Able=1,Pos=Find(From,To,flag);
    if(flag)
        ResetId(From,To,-1);
    flag=1;
    while(Pos){
        Able^=1;
        ResetId(Pos,To,flag);
        if(flag==-1)
            To=From;
        From=Pos;
        P[Pos].Delt('J');
        Pos=Find(From,To,flag);
        if(Pos)
            flag=P[Pos].Relation(To)==1?+1:-1;
    }
    return Able;
}

bool CheckOver(int flag){
    int Num[3]={0,0,0};
    for(register int i=1;i<=n;++i){
        if(!P[i].IsDead())
            ++Num[P[i].GetId()+1];
    }
    if(!Num[0]){
        if(flag)
            printf("MP\n");
        return 1;
    }
    if(!Num[1]){
        if(flag)
            printf("FP\n");
        return 1;
    }
    return 0;
}

bool Kill(int K){
    int T=K%n+1;
    while(P[T].IsDead())
        T=T%n+1;
    if(P[K].Relation(T)!=-1)
        return 0;
    ResetId(K,T,-1);
    if(P[T].Have('D'))
        P[T].Delt('D');
    else{
        P[T].Hurt();
        if(CheckOver(0))
            return 1;
        if(P[T].IsDead()){
            if(P[T].GetId()==-1)
                P[K].Getcards(3);
            if(!P[K].GetId()&&P[T].GetId()==+1)
                P[K].Discard();
        }
    }
    return 1;
}

bool Duel(int K){
    int T;
    if(P[K].GetId()==-1){
        for(register int i=1;i<=n;++i){
            if(!P[i].GetId()){
                T=i;
                break;
            }
        }
    }
    else{
        T=K%n+1;
        while(P[T].IsDead()||P[K].Relation(T)!=-1){
            T=T%n+1;
            if(T==K)
                break;
        }
    }
    if(T==K)
        return 0;
    if(Offset(K,T,-1)){
        if(!P[K].GetId()&&P[T].GetId()==+1){
            P[T].Hurt();
            if(P[T].IsDead())
                P[K].Discard();
        }
        else{
            int Now=T,Last=K;
            while(P[Now].Have('K')){
                P[Now].Delt('K');
                swap(Now,Last);
            }
            P[Now].Hurt();
            if(CheckOver(0))
                return 1;
            if(P[Now].IsDead()&&P[Now].GetId()==-1)
                P[Last].Getcards(3);
        }
    }
    return 1;
}

void AOE(int K,char c){
    for(register int i=K+1;i<=n;++i){
        if(P[i].IsDead())
            continue;
        if(Offset(K,i,0)){
            if(P[i].Have(c))
                P[i].Delt(c);
            else{
                if(!P[i].GetId()&&P[i].Relation(K)!=+1)
                    P[i].SetId(K,-1);
                P[i].Hurt();
                if(CheckOver(0))
                    break;
                if(P[i].IsDead()){
                    if(!P[K].GetId()&&P[i].GetId()==+1)
                        P[K].Discard();
                    if(P[i].GetId()==-1)
                        P[K].Getcards(3);
                }
            }
        }
    }
    if(CheckOver(0))
        return;
    for(register int i=0+1;i< K;++i){
        if(P[i].IsDead())
            continue;
        if(Offset(K,i,0)){
            if(P[i].Have(c))
                P[i].Delt(c);
            else{
                if(!P[i].GetId()&&P[i].Relation(K)!=+1)
                    P[i].SetId(K,-1);
                P[i].Hurt();
                if(CheckOver(0))
                    break;
                if(P[i].IsDead()){
                    if(!P[K].GetId()&&P[i].GetId()==+1)
                        P[K].Discard();
                    if(P[i].GetId()==-1)
                        P[K].Getcards(3);
                }
            }
        }
    }
    return;
}

void Play(int K){
    int Now=0,Flag=0;
    P[K].Getcards(2);
    while(!P[K].IsDead()){
        if(Now>=P[K].CardNum())
            break;
        char c=P[K].FindCard(Now++);
        if(c=='D')
            continue;
        if(c=='J')
            continue;
        if(c=='P'){
            if(P[K].HPNow()<4){
                Now=0;
                P[K].Delt('P');
                P[K].Recover();
            }
        }
        if(c=='K'){
            if(!Flag||P[K].IsEquip()){
                if(Kill(K)){
                    Now=0;
                    Flag=1;
                    P[K].Delt('K');
                }
            }
        }
        if(c=='Z'){
            Now=0;
            P[K].Equip();
            P[K].Delt('Z');
        }
        if(c=='F'){
            if(Duel(K)){
                Now=0;
                P[K].Delt('F');
            }
        }
        if(c=='W'){
            Now=0;
            AOE(K,'D');
            P[K].Delt('W');
        }
        if(c=='N'){
            Now=0;;
            AOE(K,'K');
            P[K].Delt('N');
        }
        if(CheckOver(0))
            break;
    }
    return;
}

void work(){
    while(true){
        for(register int K=1;K<=n;++K){
            if(P[K].IsDead())
                continue;
            Play(K);
            if(CheckOver(0))
                break;
        }
        if(CheckOver(1))
            break;
    }
    for(register int i=1;i<=n;++i){
        if(P[i].IsDead())
            printf("DEAD\n");
        else{
            P[i].Print();
            putchar('\n');
        }
    }
    return;
}

inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){
       if(ch=='-')f=-1;
       ch=getchar();
    }
    while(ch>='0'&&ch<='9'){
       x=(x<<1)+(x<<3)+ch-'0';
       ch=getchar();
    }
    return x*f;
}

int main(){

    n=read();m=read();

    for(register int i=1;i<=n;++i)
        P[i].Initialize(i);

    int MP=0;
    for(register int i=1;i<=n;++i){
        if(!P[i].GetId())
            MP=i;
    }

    for(register int i=1;i<=n;++i)
        P[i].SetId(MP,P[i].GetId());

    P[MP].SetId(MP,1);

    H.Initialize();

    work();

    return 0;
}
posted @ 2020-11-10 19:27  zjy123456  阅读(243)  评论(0编辑  收藏  举报