洛谷P2482 [SDOI2010]猪国杀 坑点总结

题目链接:https://www.luogu.com.cn/problem/P2482
总结了几个坑点…
(这种改一改都能当课设交的东西真的有人比赛的时候写得出来吗)

  • 使用锦囊牌时可能存在跳反或跳忠(打出无懈可击)的情况,一旦出现了有可能要从头检索是否有可使用的杀或决斗
  • 装备诸葛连弩时同理;
  • 对别人打出决斗自己可能会死,此时需要中断回合;
  • 反猪的决斗一定是对主猪用的;
  • 主猪杀了忠猪后,弃牌的时候不要忘了诸葛连弩;
  • 同时不要忘了此时遍历的手牌已经没了;
  • 但是不能直接中断回合,比如忠猪如果死于万箭齐发,那么在它之后还可能有反猪因此死掉,这种情况下主公会摸三张牌,回合仍可能继续;
  • 角色死后不要鞭尸,南蛮入侵、万箭齐发等需要遍历玩家的情况记得跳过死者;
  • 一有角色死亡就要记得计算距离;
  • 距离是单向的;
  • 牌堆如果没牌了会持续抽最后一张牌;
  • 无懈可击可以无限连;
  • 如果自身没有跳反/忠,那么无懈可击也不会对自己用
  • 使用过和决斗和无懈可击的角色身份一定是明确的
  • 反猪并不会帮助类反猪,如果忠猪被变成了类反猪被主猪决斗了那就只能挨打掉血
  • 由于角色死亡可能导致游戏结束,因此每次有角色死透了都要康康死的是不是主公或最后一个反贼

附上Ac代码

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

struct Player
{
    
    
    char card[2005];
    int mp_sign[15];
    int card_num=0,hp=4,card_cur=0,card_st=1;
    bool mp,zp,fp,weapon,expose;
    int wx,shan,atk;
    int uwx,u_shan;
}player[15];
char card[2005];
int n,cur=0,fst_kill,fst_jd;
bool fp_ep,zp_ep;

void get_card(int i,char ch)//获取卡牌
{
    
    
    player[i].card[++player[i].card_cur]=ch;
    ++player[i].card_num;
    if(ch=='J')
        ++player[i].wx;
    else if(ch=='D')
        ++player[i].shan;
}

int z_wx(const int &num,const int &n)//主公一派打出无懈
{
    
    
    for(int k=num,i=0;i<n;++i,k=k+1>n?1:k+1)
    {
    
    
        if(player[k].zp&&player[k].wx!=0&&player[k].hp>0)//活的忠臣
        {
    
    
            if(!player[k].expose)
                player[k].expose=zp_ep=true,player[1].mp_sign[k]=1;
            --player[k].card_num,--player[k].wx,++player[k].uwx;
            return k;
        }
        else if(player[k].mp&&player[k].wx!=0)//主公
        {
    
    
            --player[k].card_num,--player[k].wx,++player[k].uwx;
            return k;
        }
    }
    return -1;
}

int f_wx(const int &num,const int &n)//反贼一派打出无懈
{
    
    
    for(int k=num,i=0;i<n;++i,k=k+1>n?1:k+1)
    {
    
    
        if(player[k].fp&&player[k].wx!=0&&player[k].hp>0)//活的反贼
        {
    
    
            if(!player[k].expose)
                player[k].expose=fp_ep=true,player[1].mp_sign[k]=-1;
            --player[k].card_num,--player[k].wx,++player[k].uwx;
            return k;
        }
    }
    return -1;
}

void dying(const int &num,const int &m,const int &j)//濒死状态
{
    
    
    for(int i=player[j].card_st;i<=player[j].card_cur;++i)
    {
    
    
        if(player[j].card[i]=='P')//自救成功
        {
    
    
            ++player[j].hp,--player[j].card_num,player[j].card[i]=0;
            return ;
        }
    }
    if(player[j].mp)
        return ;
    int a=-1;
    for(int i=j-1>0?j-1:n;i!=j;i=i-1>0?i-1:n) //角色死亡导致距离改变
    {
    
    
        if(player[i].hp>0)
        {
    
    
            a=i;
            break;
        }
    }  
    for(int i=j+1>n?1:j+1;i!=j;i=i+1>n?1:i+1)  
    {
    
    
        if(player[i].hp>0)
        {
    
    
            player[a].atk=i;
            break;
        }
    }  
    if(player[j].fp)//反贼死亡,击杀者摸牌
    {
    
    
        cur=min(m,cur+1),get_card(num,card[cur]);
        cur=min(m,cur+1),get_card(num,card[cur]);
        cur=min(m,cur+1),get_card(num,card[cur]);
        return ;
    }
    if(player[j].zp&&player[num].mp)//主公杀死忠臣失去所有手牌
    {
    
    
        player[num].uwx=player[num].u_shan=0;
        player[num].card_num=player[num].wx=player[num].shan=0;
        player[num].card_st=player[num].card_cur+1;
        player[num].weapon=false,fst_jd=fst_kill=0;
        return ;
    }
}

bool jd(const int &a,const int &b)决斗判定
{
    
    
    while(true)
    {
    
    
        bool k_left=false;
        for(int j=player[b].card_st;j<=player[b].card_cur;++j)
        {
    
    
            if(player[b].card[j]=='K')
            {
    
    
                player[b].card[j]=0,--player[b].card_num,k_left=true;
                break;
            }
        }
        if(k_left)
        {
    
    
            k_left=false;
            for(int j=player[a].card_st;j<=player[a].card_cur;++j)
            {
    
    
                if(player[a].card[j]=='K')
                {
    
    
                    player[a].card[j]=0,--player[a].card_num,k_left=true;
                    break;
                }
            }
            if(!k_left)
                return false;
        }
        else 
            return true;
    }
}

bool get_atk_id(const int &atk,const int &num)
{
    
    
    if(player[num].mp||player[num].zp)//攻击发起人为主或忠
    {
    
    
        if(player[atk].fp&&player[atk].expose)//对方为明反时动手
            return false;
        else if(player[num].mp&&player[num].mp_sign[atk]==-1)//主公会打类反
            return false;
    }
    else//反贼能动手了
    {
    
    
        if((player[atk].zp&&player[atk].expose)||player[atk].mp)//当且仅当对方为明忠或主时动手
            return false;
    }
    return true;//非敌对单位
}

bool z_f_wx(const int &num)//主公一排派先出无懈
{
    
    
    int temp=num;
    while(true)
    {
    
    
        temp=z_wx(temp,n);
        if(temp==-1)
            return false;
        else
        {
    
    
            temp=f_wx(temp,n);
            if(temp==-1)
                return true;
        }
    }

}

bool f_z_wx(const int &num)//反贼一排派先出无懈
{
    
    
    int temp=num;
    while(true)
    {
    
    
        temp=f_wx(temp,n);
        if(temp==-1)
            return false;
        else
        {
    
    
            temp=z_wx(temp,n);
            if(temp==-1)
                return true;
        }
    }
}

int main()
{
    
    
    ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    string s;
    char ch;
    bool atk_id;
    int m,num=1,kill,num_fp=0,atk;
    cin>>n>>m;
    for(int i=1;i<=n;++i)//开局
    {
    
    
        cin>>s;
        if(i!=n)
            player[i].atk=i+1;
        else 
            player[i].atk=1;
        if(s=="MP")
            player[i].mp=true;
        else if(s=="ZP")
            player[i].zp=true;
        else 
            player[i].fp=true,++num_fp;
        for(int j=1;j<=4;++j)
        {
    
    
            cin>>ch;
            get_card(i,ch);
        }
    }
    for(int i=1;i<=m;++i)
        cin>>card[i];
    if(num_fp==0)
        goto game_over;
    fp_ep=zp_ep=false;//一开始谁也没跳
    while(true)
    {
    
    
        cur=min(m,cur+1),get_card(num,card[cur]);
        cur=min(m,cur+1),get_card(num,card[cur]);
        kill=fst_kill=fst_jd=0;//当前角色出杀数
        atk=player[num].atk;//获取可杀对象
        atk_id=get_atk_id(atk,num);//获取是否为非敌对单位
        for(int i=player[num].card_st;i<=player[num].card_cur;++i)
        {
    
    
            if(atk!=player[num].atk)//可杀对象被aoe死了换人了
            {
    
    
                atk=player[num].atk;
                bool temp=get_atk_id(atk,num);
                if(temp!=atk_id)//敌对关系变化
                {
    
    
                    if((kill<=0||player[num].weapon)&&atk_id)//还能出杀且对方为敌对单位
                    {
    
    
                        if(fst_kill!=0)//如果前面有没出的杀就跳回去出杀
                            i=fst_kill,fst_kill=0;
                    }
                    atk_id=temp;
                }
            }
            else if(fp_ep||zp_ep)//有人跳了,检查可攻击对象是否已敌对
            {
    
    
                bool temp=get_atk_id(atk,num);
                if(temp!=atk_id)//敌对关系变化
                {
    
    
                    if((kill<=0||player[num].weapon)&&atk_id)//还能出杀且对方为敌对单位
                    {
    
    
                        if(fst_kill!=0)//如果前面有没出的杀就跳回去出杀
                            i=fst_kill,fst_kill=0;
                    }
                    atk_id=temp;
                }
            }
            if((player[num].zp||num==1)&&fp_ep&&fst_jd!=0)//在主或忠的回合有人跳反了,且前面有决斗
            {
    
    
                i=min(i,fst_jd);
                fst_jd=0;
            }
            if(player[num].card[i]=='J'||player[num].card[i]=='D'||player[num].card[i]==0)//响应牌或出过的牌
                continue;
            if(player[num].card[i]=='Z')//装备诸葛连弩
            {
    
    
                player[num].card[i]=0,--player[num].card_num;
                if(!player[num].weapon)//此前未装备
                {
    
    
                    player[num].weapon=true;
                    if(fst_kill!=0)//前边有杀,跳转
                        i=fst_kill-1,fst_kill=0;
                }
            }
            else if(player[num].card[i]=='P')//你在想peach
            {
    
    
                if(player[num].hp<4)
                    player[num].card[i]=0,++player[num].hp,--player[num].card_num;
                else
                    continue;
            }
            else if(player[num].card[i]=='N')//使用南蛮入侵
            {
    
    
                player[num].card[i]=0,--player[num].card_num;
                for(int j=num+1>n?1:num+1;j!=num;j=j+1>n?1:j+1)//玩家结算
                {
    
    
                    if(player[j].hp<=0)
                        continue;
                    if(player[j].mp||(player[j].zp&&player[j].expose))//受害者为明忠或主
                    {
    
    
                        if(z_f_wx(num))//无懈可击生效
                            continue;
                        else
                        {
    
    
                            bool sha_y=false;
                            for(int k=player[j].card_st;k<=player[j].card_cur;++k)
                            {
    
    
                                if(player[j].card[k]=='K')
                                {
    
    
                                    --player[j].card_num;
                                    player[j].card[k]=0;
                                    sha_y=true;
                                    break;
                                }
                            }
                            if(!sha_y)//没杀
                            {
    
    
                                --player[j].hp;
                                if(player[j].hp<=0)
                                {
    
    
                                    dying(num,m,j);
                                    if(player[1].hp<=0)
                                        goto game_over;
                                    else if(num==1&&player[j].zp)
                                        i=player[num].card_cur;
                                }
                                if(j==1&&player[num].expose==false)//未明身份导致主公掉血视为类反
                                    player[1].mp_sign[num]=-1;
                            }
                            else
                                continue;
                        }
                    }
                    else if(player[j].fp&&player[j].expose)//受害者为明反
                    {
    
    
                        if(f_z_wx(num))//无懈可击生效
                            continue;
                        else
                        {
    
    
                            bool sha_y=false;
                            for(int k=player[j].card_st;k<=player[j].card_cur;++k)
                            {
    
    
                                if(player[j].card[k]=='K')
                                {
    
    
                                    --player[j].card_num;
                                    player[j].card[k]=0;
                                    sha_y=true;
                                    break;
                                }
                            }
                            if(!sha_y)//没杀
                            {
    
    
                                --player[j].hp;
                                if(player[j].hp<=0)
                                {
    
    
                                    dying(num,m,j);
                                    if(player[j].hp<=0)
                                    {
    
    
                                        --num_fp;
                                        if(num_fp<=0)
                                        {
    
    
                                            player[num].card_cur-=3;
                                            player[num].card_num-=3;
                                            goto game_over;
                                        }
                                    }
                                }
                            }
                            else 
                                continue;
                        }

                    }
                    else //身份不明
                    {
    
    
                        bool sha_y=false;
                        for(int k=player[j].card_st;k<=player[j].card_cur;++k)
                        {
    
    
                            if(player[j].card[k]=='K')
                            {
    
    
                                --player[j].card_num;
                                player[j].card[k]=0;
                                sha_y=true;
                                break;
                            }
                        }
                        if(!sha_y)//没杀
                        {
    
    
                            --player[j].hp;
                            if(player[j].hp<=0)
                            {
    
    
                                dying(num,m,j);
                                if(player[j].hp<=0)
                                {
    
    
                                    if(player[j].fp)
                                    {
    
    
                                        --num_fp;
                                        if(num_fp<=0)
                                        {
    
    
                                            player[num].card_cur-=3;
                                            player[num].card_num-=3;
                                            goto game_over;
                                        }
                                    }
                                    else if(num==1&&player[j].zp)//主杀忠
                                        i=player[num].card_cur;
                                }
                            }
                        }
                    }
                }
            }
            else if(player[num].card[i]=='W')//使用万箭齐发
            {
    
    
                player[num].card[i]=0,--player[num].card_num;
                for(int j=num+1>n?1:num+1;j!=num;j=j+1>n?1:j+1)//玩家结算
                {
    
    
                    if(player[j].hp<=0)
                        continue;
                    if(player[j].mp||(player[j].zp&&player[j].expose))//明忠或主
                    {
    
    
                        if((z_f_wx(num)))//无懈可击生效
                            continue;
                        else
                        {
    
    
                            if(player[j].shan>0)
                            {
    
    
                                --player[j].card_num;
                                --player[j].shan,++player[j].u_shan;
                            }
                            else//没闪
                            {
    
    
                                --player[j].hp;
                                if(player[j].hp<=0)
                                {
    
    
                                    dying(num,m,j);
                                    if(player[1].hp<=0)
                                        goto game_over;
                                    else if(num==1&&player[j].zp)//主杀忠
                                        i=player[num].card_cur;
                                }
                                if(j==1&&player[num].expose==false)//未明身份导致主公掉血视为类反
                                    player[1].mp_sign[num]=-1;
                            }
                        }
                    }
                    else if(player[j].fp&&player[j].expose)//明反
                    {
    
    
                        if(f_z_wx(num))//无懈可击生效
                            continue;
                        else
                        {
    
    
                            if(player[j].shan>0)
                            {
    
    
                                --player[j].card_num;
                                --player[j].shan,++player[j].u_shan;
                            }
                            else//没闪
                            {
    
    
                                --player[j].hp;
                                if(player[j].hp<=0)
                                {
    
    
                                    dying(num,m,j);
                                    if(player[j].hp<=0)
                                    {
    
    
                                        --num_fp;
                                        if(num_fp<=0)
                                        {
    
    
                                            player[num].card_cur-=3;
                                            player[num].card_num-=3;
                                            goto game_over;
                                        }
                                    }
                                }
                            }
                        }
                    }
                    else //身份不明
                    {
    
    
                        if(player[j].shan>0)
                        {
    
    
                            --player[j].card_num;
                            --player[j].shan,++player[j].u_shan;
                        }
                        else//没闪
                        {
    
    
                            --player[j].hp;
                            if(player[j].hp<=0)
                            {
    
    
                                dying(num,m,j);
                                if(player[j].hp<=0)
                                {
    
    
                                    if(player[j].fp)
                                    {
    
    
                                        --num_fp;
                                        if(num_fp<=0)
                                        {
    
    
                                            player[num].card_cur-=3;
                                            player[num].card_num-=3;
                                            goto game_over;
                                        }
                                    }
                                    else if(num==1&&player[j].zp)//主杀忠
                                        i=player[num].card_cur;
                                }
                            }
                        }
                    }
                }
            }
            else if(player[num].card[i]=='K')//有杀
            {
    
    
                if(((!player[num].weapon)&&kill>0)||atk_id)//出杀次数上限了或对方为非攻击对象
                {
    
    
                    if(fst_kill==0)
                        fst_kill=i;
                    continue;
                }
                else
                {
    
    
                    player[num].card[i]=0,--player[num].card_num,++kill;//杀人啦
                    if(player[atk].shan>0)//嘿嘿打不到
                        ++player[atk].u_shan,--player[atk].shan,--player[atk].card_num;
                    else 
                    {
    
    
                        --player[atk].hp;//夭寿了
                        if(player[atk].hp<=0)//死人啦
                        {
    
    
                            dying(num,m,atk);//看看还有救没有
                            if(player[atk].hp<=0)//救不了,告辞
                            {
    
    
                                if(player[atk].fp)//是个反贼
                                {
    
    
                                    --num_fp;
                                    if(num_fp<=0)//反贼死光了
                                    {
    
    
                                        player[num].card_cur-=3;
                                        player[num].card_num-=3;
                                        goto game_over;
                                    }
                                }
                                else if(player[atk].zp)//对不起你是个好人
                                {
    
    
                                    if(num==1&&player[atk].zp)//主杀忠
                                        i=player[num].card_cur;
                                }
                                else if(player[atk].mp)//没了没了
                                    goto game_over;
                            }
                        }
                        else if(atk==1)//检查是否有跳反
                        {
    
    
                            if(!player[num].expose)
                                player[num].expose=fp_ep=true;
                        }
                        
                    }
                }
            }
            else if(player[num].card[i]=='F')//决斗
            {
    
    
                if(player[num].mp)//主公
                {
    
    
                    int temp=0;
                    for(int j=num+1>n?1:num+1;j!=num;j=j+1>n?1:j+1)
                    {
    
    
                        if(player[j].hp<=0)//起码得活着
                            continue;
                        if(player[num].mp_sign[j]==-1)//类反或明反
                        {
    
    
                            temp=j;
                            break;
                        }
                    }
                    if(temp!=0)
                    {
    
    
                        player[num].card[i]=0,--player[num].card_num;
                        if(player[temp].zp)//误伤主公的类反忠
                        {
    
    
                            --player[temp].hp;
                            if(player[temp].hp<=0)
                            {
    
    
                                dying(num,m,temp);
                                if(player[temp].hp<=0&&num==1&&player[atk].zp)//主杀忠
                                    i=player[num].card_cur;
                            }
                        }
                        else if(player[temp].fp)//反贼
                        {
    
    
                            if(player[temp].expose&&f_z_wx(num))//明反被无懈救了
                                continue;
                            if(jd(num,temp))//主公赢了
                            {
    
    
                                --player[temp].hp;
                                if(player[temp].hp<=0)
                                {
    
    
                                    dying(num,m,temp);
                                    if(player[temp].hp<=0)
                                    {
    
    
                                        --num_fp;
                                        if(num_fp<=0)
                                        {
    
    
                                            player[num].card_cur-=3;
                                            player[num].card_num-=3;
                                            goto game_over;
                                        }
                                    }
                                }
                            }
                            else//主公输了
                            {
    
    
                                --player[num].hp;
                                if(player[num].hp<=0)
                                {
    
    
                                    dying(temp,m,num);
                                    if(player[num].hp<=0)
                                        goto game_over;
                                }
                                else if(!player[temp].expose)
                                    player[temp].expose=fp_ep=true;
                            }
                        }
                    }
                    else
                    {
    
    
                        if(fst_jd==0)
                            fst_jd=i;
                        continue;
                    }
                }
                else if(player[num].zp)//忠臣
                {
    
    
                    int temp=0;
                    for(int j=num+1>n?1:num+1;j!=num;j=j+1>n?1:j+1)
                    {
    
    
                        if(player[j].hp<=0)//死的不要
                            continue;
                        if(player[j].fp&&player[j].expose)//明反
                        {
    
    
                            temp=j;
                            break;
                        }
                    }
                    if(temp!=0)
                    {
    
    
                        player[num].card[i]=0,--player[num].card_num;
                        if(!player[num].expose)
                            player[num].expose=zp_ep=true,player[1].mp_sign[num]=1;
                        if(f_z_wx(num))
                            continue;
                        else 
                        {
    
    
                            if(jd(num,temp))//忠臣赢了
                            {
    
    
                                --player[temp].hp;
                                if(player[temp].hp<=0)
                                {
    
    
                                    dying(num,m,temp);
                                    if(player[temp].hp<=0)
                                    {
    
    
                                        --num_fp;
                                        if(num_fp<=0)
                                        {
    
    
                                            player[num].card_cur-=3;
                                            player[num].card_num-=3;
                                            goto game_over;
                                        }
                                    }
                                }
                            }
                            else//忠臣输了
                            {
    
    
                                --player[num].hp;
                                if(player[num].hp<=0)
                                {
    
    
                                    dying(temp,m,num);
                                    if(player[num].hp<=0)//不仅输了还被打死了
                                        break;
                                }
                            }
                        }
                    }
                    else
                    {
    
    
                        if(fst_jd==0)
                            fst_jd=i;
                        continue;
                    }
                }
                else if(player[num].fp)//反贼
                {
    
    
                    player[num].card[i]=0,--player[num].card_num;
                    if(!player[num].expose)
                        fp_ep=player[num].expose=true,player[1].mp_sign[num]=-1;
                    if(z_f_wx(num))//无懈可击生效
                        continue;
                    else
                    {
    
    
                        if(jd(num,1))//反贼赢了
                        {
    
    
                            --player[1].hp;
                            if(player[1].hp<=0)
                            {
    
    
                                dying(num,m,1);
                                if(player[1].hp<=0)
                                    goto game_over;
                            }
                        }
                        else//反贼输了
                        {
    
    
                            --player[num].hp;
                            if(player[num].hp<=0)
                            {
    
    
                                dying(1,m,num);
                                if(player[num].hp<=0)
                                {
    
    
                                    --num_fp;
                                    if(num_fp<=0)
                                    {
    
    
                                        player[num].card_cur-=3;
                                        player[num].card_num-=3;
                                        goto game_over;
                                    }
                                    break;
                                }
                            }
                        }
                    }
                }
            }
        }
        do{
    
    
            num=num+1>n?1:num+1;
        }while(player[num].hp<=0);
    }
    game_over:
    if(player[1].hp<=0)
        cout<<"FP"<<endl;
    else
        cout<<"MP"<<endl;
    for(int i=1;i<=n;++i)
    {
    
    
        if(player[i].hp<=0)
            cout<<"DEAD"<<endl;
        else
        {
    
    
            for(int j=player[i].card_st;j<=player[i].card_cur;++j)
            {
    
    
                if(player[i].card[j]=='D')
                {
    
    
                    if(player[i].u_shan>0)
                        --player[i].u_shan;
                    else
                        cout<<"D ";
                }
                else if(player[i].card[j]=='J')
                {
    
    
                    if(player[i].uwx>0)
                        --player[i].uwx;
                    else
                        cout<<"J ";
                }
                else if(player[i].card[j]!=0)
                    cout<<player[i].card[j]<<" ";
            }
            cout<<endl;
        }
    }
}

猜你喜欢

转载自blog.csdn.net/suolk/article/details/114994828