[挑战记录]猪国杀

觉得没有做过猪国杀的人生是不完整的!
于是决定开肝(
先在前面写上需要注意的点
1.找清目标,判断好角色;
2.装上诸葛连弩后,前面的杀也能用;
3.决斗时,进攻发起者可以要使用多张杀,所以要处理好决斗后,手牌剩余部分;
4.决斗时,可能进攻发起者会GG(不知道他怎么想的,不愧是pig),此时要停止他的回合;
5.万箭齐发(南蛮入侵)时,可能会有多人GG,可能会摸多次牌;
6.万箭齐发(南蛮入侵)时,可能会有多人GG,同时发动者是主公,不仅杀死了忠臣,也杀死了反贼,此时也要考虑弃掉所有手牌和摸三张牌的顺序;
7.决斗时,主公认为对面是类反贼,实际上是忠臣,忠臣要牺牲一滴血;
8.在决斗时,发起者会明确身份;在万箭齐发(南蛮入侵)时,可能并不会,但有可能成为类反贼;
9.无懈不可能先手打出,并不代表在自己回合内就不用出无懈;
10.无懈的优先级很高(比一般锦囊牌都高);
11.当一个人使用了无懈,他的身份就完全表明了;
12.无懈看似是最复杂,但是实际上相当于一个补丁(尽管有挺多的细节);
下面还有一些全局的注意点:
13.主公杀死忠臣,一定要把装备给弃了;
14.关于一轮能否出多次杀,要注意判断;
15.一张牌,你出了,就相当于弃置了,不管最后是否生效;
16.最形象的方法存手牌显然是链表,但考虑到实际需要,一般直接开数组(这里我用了维护两个指针,能过)
17.要分清在自己的回合出牌和在别人的回合出牌,最好用不同方法处理,但处理也有很多细节(因人而异);
18.注意主公也会对类反贼表敌意;
19.杀,桃,无懈都是有可能在自己回合打出的“响应牌”(就是回击别人的牌),要注意处理方法(要看清是自己回合还是他人回合出的牌);
20.严格意义上,除了“桃”,在自己回合出了每一张牌后,都可能会激活这张牌前面的牌;
21.注意这里的距离是单向的,而不是双向的,而且恒为 \(1\)
22.存在用无懈无懈掉自己的锦囊牌的情况;
23.阵亡的人已经没有任何价值,直接跳过他;
24.一旦出现胜利局面,就要停止一切操作,但是需要把没有整理好的手牌整理好;
25.对于一个人,要是把手牌扫了一遍,没有出任何牌,就结束出牌;
26.一个人死了后,及时更新上一个玩家的下一个玩家nxt(不必 \(\mathcal{O(1)}\) 求);
27.注意一个人处于濒死状态的处理,每当有一个人死了,都要判断一下游戏是否结束了;
28.当牌堆没有牌时,要一直摸最后一张牌。

2022-09-22 18:45

吃着葡萄欣赏“人走机子开”
开始答题

19:29

看错一次题目(必须从左边开始摸牌)

19:54

又看错一次题目(类反猪和反猪是不同的)

20:03

\(\color{black}{C}\color{red}{reator\_157}\) 大佬入坑

20:09

初步完成 \(K\) 函数构建

20:17

基本完成 \(P\) 函数,以及完善了 \(K\) 函数

20:41

完成 \(F\) 函数,顺便写了不知道有没有用的 \(passive\_kill\)

21:06

\(\color{black}{C}\color{red}{reator\_157}\) 大佬弃坑力(悲

21:38

将先前的函数全部修正,加入死人 \(victim\) 函数和判断胜利 \(victory\) 函数

今日码量: \(158\)

09-23

早上跑操加圈(悲)

06:43

完成 \(N\) 函数,\(W\) 函数

06:52

发现大锅需要补(类反猪不会被忠猪攻击)

08:27

开始施工主函数 \(play\)

09:50

交了第一次,TLE0

10:30

发现错误:猪的类型判断出错
反 猪 护 主 猪

11:08

发现一个巨大的锅,交了两次 \(0\)
主要问题在于无限摸牌 \(\cdots\)

14:08

查明主要问题:摸牌的时候上限写成了 \(n\)
\(10\) 分!

14:28

\(300\)

14:52

完成了一些辅助函数,完善 \(play\) 函数

15:27

决斗函数好像伪了,决斗攻击距离不为 \(1\)
开始大修

16:23

\(15\) 分!

16:51

\(20\) 分!

17:18

眼瞎了,没看见“如果有机会向主猪表敌意”
然后一只反猪就在主公空城 \(+\) 一点血的情况下对着满杀的忠臣用了决斗
乐死了

17:25

\(25\) 分力!

17:38

\(30\) 分!

17:53

发现链表哪里挂了,第二个子任务完成
\(35\) 分!
同时代码达到了 \(10.3K\)
晚上打 \(CF\)

今日码量:\(348\)

09-24

上午改题

15:00

开始调题,写 \(J\) 函数

15:46

\(40\) 分!

16:32

《关于一只忠猪出了万箭齐发打了主公这件事》
《关于这只忠猪已经跳忠了这件事》
《关于另外一只忠猪用无懈帮主公挡了,跳忠这件事》
《关于出万箭齐发的忠猪对用无懈的忠猪甩了一张决斗这件事》
好耶

16:36

《关于反猪帮主猪出了张无懈可击这件事》

17:08

原来当前出完牌后可以直接无懈自己,我大意了啊

17:10

\(55\) 分!!!

18:45

吃完晚饭回来写
发现两重循环只跳了一层,我是 \(\operatorname{SB}\)

19:04

\(65\) 分了

19:13

《关于主猪把忠猪给自己的无懈可击无懈掉了这档子事》

19:16

\(90\) 分!!!

19:21

为啥我给死人用了无懈可击?

19:26

\(95\) 分,只差一步!

19:30

\(\mathfrak{AC}\)

385行,12.05KB,100分
#include<cstdio>
#include<cstring>
#include<string>
#include<iostream>
#define WR WinterRain
#define int long long
using namespace std;
const int WR=10010;
struct Pig{
    int opt;//0:主 1:忠 2:反
    int pos;//目前状态,true表示忠猪
    bool dead,equip,kill;
    int nxt;
    int HP,l,r;
    char card[WR];
    bool vis[WR];
}pig[11];
char card[WR];
int n,m;
int l,cntf;
int read(){
    int s=0,w=1;
    char ch=getchar();
    while(ch>'9'||ch<'0'){
        if(ch=='-') w=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9'){
        s=(s<<3)+(s<<1)+ch-'0';
        ch=getchar();
    }
    return s*w;
}
void getcard(int id){
    if(l!=m) l++;
    pig[id].card[++pig[id].r]=card[l];
    //cout<<"Pig "<<id<<" get card "<<card[l]<<",l="<<pig[id].l<<",r="<<pig[id].r<<endl;
}
void victory(int opt){
    if(opt) printf("FP\n");
    else printf("MP\n");
    for(int i=1;i<=n;i++){
        if(pig[i].dead) printf("DEAD\n");
        else{
            for(int j=pig[i].l;j<=pig[i].r;j++){
                if(!pig[i].vis[j]) printf("%c ",pig[i].card[j]);
            }
            printf("\n");
        }
    }
}
bool victim(int frm,int body){
    //cout<<body<<" DEAD"<<endl;
    if(pig[body].opt==2){
        cntf--;
        if(!cntf){
            victory(0);
            return true;
        }
        getcard(frm);getcard(frm);getcard(frm);
    }else if(pig[body].opt==1&&pig[frm].opt==0){
        for(int i=pig[frm].l;i<=pig[frm].r;i++) pig[frm].vis[i]=true;
        pig[frm].equip=false;
    }else if(pig[body].opt==0){
        victory(1);
        return true;
    }
    return false;
}
bool flawless(int frm,int id){
    if(pig[id].pos==-1) return false;
    bool flag=false,vis=true;
    //cout<<id<<" flawlessing..."<<endl;
    while(vis){
        vis=false;
        int pos=frm;
        do{
            if(((pig[id].pos==pig[pos].opt)||(pig[id].pos==0&&pig[pos].opt==1)
                ||(pig[id].pos==1&&pig[pos].opt==0))^flag){
                for(int i=pig[pos].l;i<=pig[pos].r;i++){
                    if(pig[pos].card[i]=='J'&&(!pig[pos].vis[i])){
                        //cout<<pos<<" flawlessed"<<endl;
                        if(pig[pos].pos==-1){
                            if(flag^(pig[id].pos==2)) pig[pos].pos=2;
                            else pig[pos].pos=1;
                        }
                        pig[pos].vis[i]=true;
                        flag^=1;vis=true;
                        while(pig[pos].vis[pig[pos].l]) pig[pos].l++;
                        break;
                    }
                }
            }
            while(pig[pig[pos].nxt].dead) pig[pos].nxt=pig[pig[pos].nxt].nxt;
            pos=pig[pos].nxt;
            if(pos==frm) break;
        }while(pos!=frm);
    }
    //cout<<(flag?"Success":"Failed")<<endl;
    return flag;
}
int peach(int id){
    //cout<<"Peached "<<id<<endl;
    int heal=0;
    for(int i=pig[id].l;i<=pig[id].r;i++){
        if((!pig[id].vis[i])&&pig[id].card[i]=='P'){
            heal++;pig[id].vis[i]=true;
        }
        if(heal) break;
    }
    while(pig[id].vis[pig[id].l]) pig[id].l++;
    return heal;
}
int save(int frm,int to){
    if(peach(to)==0){
        pig[to].dead=true;
        if(victim(frm,to)) return -1;
        else return 1;
    }else pig[to].HP=1;
    //cout<<to<<" saved itself"<<endl;
    return 0;
}
int kill(int frm,int to){//返回0表示被闪掉,1表示掉了血没死,2表示杀死了,-1表示结束了
    //cout<<frm<<" killing "<<to<<endl;
    if(pig[frm].pos!=0){
        if(pig[to].pos==2) pig[frm].pos=1;
        else if(pig[to].pos==0||pig[to].pos==1) pig[frm].pos=2;
    }
    for(int i=pig[to].l;i<=pig[to].r;i++){
        if((!pig[to].vis[i])&&pig[to].card[i]=='D'){
            pig[to].vis[i]=true;
            //cout<<"...failed\n";
            return 0;
        }
    }
    pig[to].HP--;
    if(!pig[to].HP){
        int opt=save(frm,to);
        if(opt==-1) return -1;
    }
    while(pig[to].vis[pig[to].l]) pig[to].l++;
    if(pig[to].HP) return 1;
    else return 2;
}
int arrow_kill(int frm,int to){//返回0表示被闪掉,1表示掉了血没死,2表示杀死了,-1表示结束了
    //cout<<frm<<" arrow_killing "<<to<<endl;
    for(int i=pig[to].l;i<=pig[to].r;i++){
        if((!pig[to].vis[i])&&pig[to].card[i]=='D'){
            pig[to].vis[i]=true;
            //cout<<"...failed\n";
            return 0;
        }
    }
    pig[to].HP--;
    if(!pig[to].HP){
        int opt=save(frm,to);
        if(opt==-1) return -1;
    }
    while(pig[to].vis[pig[to].l]) pig[to].l++;
    if(pig[to].HP) return 1;
    else return 2;
}
bool execute_kill(int pos){
    pig[pos].kill=true;
    int res=kill(pos,pig[pos].nxt);
    if(res==-1) return false;
    else if(res==2) pig[pos].nxt=pig[pig[pos].nxt].nxt;
    return true;
}
bool passive_kill(int id){
    for(int i=pig[id].l;i<=pig[id].r;i++){
        if((!pig[id].vis[i])&&pig[id].card[i]=='K'){
            pig[id].vis[i]=true;
            while(pig[id].vis[pig[id].l]) pig[id].l++;
            return true;
        }
    }
    while(pig[id].vis[pig[id].l]) pig[id].l++;
    return false;
}
int duel(int frm,int to){
    //cout<<frm<<" dueling "<<to<<endl;
    if(pig[frm].pos!=0){
        if(pig[to].pos==2) pig[frm].pos=1;
        else if(pig[to].pos==0||pig[to].pos==1) pig[frm].pos=2;
        //cout<<"Pig "<<frm<<" is "<<pig[frm].pos<<endl;
    }
    if(flawless(frm,to)) return 0;
    if(pig[frm].opt==0&&pig[to].opt==1){
        pig[to].HP--;
        if(!pig[to].HP) return save(frm,to);
        else return 0;
    }
    while(1==1){
        if(!passive_kill(to)){
            //cout<<to<<" failed"<<endl;
            pig[to].HP--;
            if(!pig[to].HP) return save(frm,to);
            else return 0;
        }
        if(!passive_kill(frm)){
            //cout<<frm<<" failed"<<endl;
            pig[frm].HP--;
            if(!pig[frm].HP) return save(to,frm)*2;
            else return 0;
        }
    }
}
int execute_duel(int pos,int to){
    int res=duel(pos,to);
    if(res<0) return 0;
    else if(!res) return 1;
    else if(res==1){
        //cout<<to<<"Dead"<<endl;
        int tmp=pig[pos].nxt;
        while(pig[tmp].nxt!=to) tmp=pig[tmp].nxt;
        pig[tmp].nxt=pig[to].nxt;
        return 2;
    }else{
        //cout<<pos<<"Dead"<<endl;
        int tmp=pig[to].nxt;
        while(pig[tmp].nxt!=pos) tmp=pig[tmp].nxt;
        pig[tmp].nxt=pig[pos].nxt;
        return 2;
    }
}
int invade(int id){
    for(int i=pig[id].nxt;i!=id;i=pig[i].nxt){
        if(pig[id].dead) continue;
        if(flawless(id,i)) continue;
        if(!passive_kill(i)){
            pig[i].HP--;
            //cout<<i<<"'s HP="<<pig[i].HP<<endl;
            if(pig[i].pos==0&&pig[id].pos==-1) pig[id].pos=3;
            if(!pig[i].HP&&save(id,i)==-1) return -1;
        }
    }
    return 0;
}
int arrow(int id){
    for(int i=pig[id].nxt;i!=id;i=pig[i].nxt){
        if(pig[id].dead) continue;
        if(flawless(id,i)) continue;
        int res=arrow_kill(id,i);
        if(res==-1) return -1;
        else if(res==1){
            if(pig[i].pos==0&&pig[id].pos==-1) pig[id].pos=3;
        }
    }
    return 0;
}
void crossbow(int id){
    pig[id].equip=true;
}
void play(){
    int pos=1;
    while(1==1){
        getcard(pos),getcard(pos);
        pig[pos].kill=false;
        bool opt=true;
        while(opt){
            if(pig[pos].dead) break;
            opt=false;
            for(int i=pig[pos].l;i<=pig[pos].r;i++){
                //cout<<"Pig "<<pos<<"'s card "<<i<<" is "<<pig[pos].card[i]<<",vis is "<<pig[pos].vis[i]<<endl;
                if(pig[pos].card[i]=='P'&&pig[pos].HP<4&&(!pig[pos].vis[i])){
                    //cout<<"Pig "<<pos<<" use peach,HP="<<pig[pos].HP+1<<endl;
                    peach(pos);pig[pos].HP++;
                    opt=true;break;
                }
                if(pig[pos].card[i]=='N'&&(!pig[pos].vis[i])){
                    //cout<<"Pig "<<pos<<" used SouthPig_Invade"<<endl;
                    opt=true;
                    pig[pos].vis[i]=true;
                    int res=invade(pos);
                    if(res==-1) return;
                    else break;
                }
                if(pig[pos].card[i]=='W'&&(!pig[pos].vis[i])){
                    //cout<<"Pig "<<pos<<" used Arrays_Shoot"<<endl;
                    opt=true;
                    pig[pos].vis[i]=true;
                    int res=arrow(pos);
                    if(res==-1) return;
                    else break;
                }
                if(pig[pos].card[i]=='Z'&&(!pig[pos].vis[i])){
                    //cout<<"Pig "<<pos<<" equipped crossbow"<<endl;
                    opt=true;
                    pig[pos].vis[i]=true;
                    crossbow(pos);
                    break;
                }
                if(pig[pos].card[i]=='F'&&(!pig[pos].vis[i])){
                    if(pig[pos].opt==2){
                        opt=true;pig[pos].vis[i]=true;
                        if(execute_duel(pos,1)) break;
                        else return;
                    }else if(pig[pos].opt==1){
                        bool tmp=false;
                        for(int j=pig[pos].nxt;j!=pos;j=pig[j].nxt){
                            if(pig[j].pos==2){
                                opt=true;pig[pos].vis[i]=true;
                                if(execute_duel(pos,j)){
                                    tmp=true;break;
                                }
                                else return;
                            }
                        }
                        if(tmp) break;
                    }else{
                        bool tmp=false;
                        for(int j=pig[pos].nxt;j!=pos;j=pig[j].nxt){
                            if(pig[pig[pos].nxt].pos==2||pig[pig[pos].nxt].pos==3){
                                opt=true;pig[pos].vis[i]=true;
                                if(execute_duel(pos,j)){
                                    tmp=true;break;
                                }
                                else return;
                            }
                        }
                        if(tmp) break;
                    }
                }
                if(pig[pos].card[i]=='K'&&(!pig[pos].vis[i])&&((!pig[pos].kill)||pig[pos].equip)){                    if(pig[pos].kill&&(!pig[pos].equip)) continue;
                    if(pig[pos].opt==2){
                        if(pig[pig[pos].nxt].pos==0||pig[pig[pos].nxt].pos==1){
                            opt=true;pig[pos].vis[i]=true;
                            if(execute_kill(pos)) break;
                            else return;
                        }
                    }else if(pig[pos].opt==1){
                        if(pig[pig[pos].nxt].pos==2){
                            opt=true;pig[pos].vis[i]=true;
                            if(execute_kill(pos)) break;
                            else return;
                        }
                    }else if(pig[pig[pos].nxt].pos==2||pig[pig[pos].nxt].pos==3){
                        opt=true;pig[pos].vis[i]=true;
                        if(execute_kill(pos)) break;
                        else return;
                    }
                }
            }
            while(pig[pos].vis[pig[pos].l]) pig[pos].l++;
            while(pig[pig[pos].nxt].dead) pig[pos].nxt=pig[pig[pos].nxt].nxt;
        }
        while(pig[pos].vis[pig[pos].l]) pig[pos].l++;
        pos=pig[pos].nxt;
        // for(int i=1;i<=n;i++){
        //     //cout<<i<<"'s role is "<<pig[i].opt<<",now is "<<pig[i].pos<<",HP is "<<pig[i].HP<<endl;
        //     for(int j=pig[i].l;j<=pig[i].r;j++){
        //         if(!pig[i].vis[j]) //cout<<pig[i].card[j]<<" ";
        //     }
        //     //cout<<endl;
        // }
        // //cout<<endl;
    }
}
signed main(){
    n=read(),m=read();
    for(int i=1;i<=n;i++){
        char str[WR];
        scanf("%s",str+1);
        pig[i].HP=4;
        pig[i].pos=-1;
        pig[i].nxt=i%n+1;
        pig[i].l=1;pig[i].r=4;
        if(str[1]=='M') pig[i].opt=0;
        else if(str[1]=='F') pig[i].opt=2,cntf++;
        else pig[i].opt=1;
        for(int j=1;j<=4;j++){
            scanf("%s",str+1);
            pig[i].card[j]=str[1];
        }
    }
    pig[1].pos=0;
    for(int i=1;i<=m;i++){
        char str[WR];
        scanf("%s",str+1);
        card[i]=str[1];
    }
    play();
    return 0;
}

用时长达将近3天,果然我是废物/kk
image

image
image
image
image

posted @ 2022-09-24 19:45  冬天丶的雨  阅读(239)  评论(5编辑  收藏  举报
Live2D