题目传送门

最近题荒,不知道做什么题,就心血来潮挖了一个大坑

一堆猪玩《猪国杀》,想想就\(interesting\)

最终万分艰难的\(A\)掉了, 留贴纪念


坑点

这道题,嗯……,可以说,全是坑点……

  1. 如果牌堆没牌了,那么会一直摸最后一张牌
  2. 距离的意思其实是:每只猪只能杀到他逆时针方向的第一只存活的猪
  3. 主猪杀死忠臣后一定要把牌弃的的干干净净,不要忘了诸葛连弩
  4. 出无懈可击和杀以及决斗都会暴露身份
  5. 反猪只会和主猪决斗
  6. 无懈可击一定要注意,只会给跳身份的人用
  7. 主公默认已跳身份

其他的还有一堆的坑点,写的时候一定要注意

调试方法

可以做一个解说器,输出游戏过程,然后下载\(LOJ\)上的数据,与\(AC\)代码比较输出的过程,效果十分不错

解说器示例:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#define LL long long
using namespace std;
LL read() {
    LL k = 0, f = 1; char c = getchar();
    while(c < '0' || c > '9') {
        if(c == '-') f = -1;
        c = getchar();
    }
    while(c >= '0' && c <= '9')
      k = k * 10 + c - 48, c = getchar();
    return k * f;
}
char read_c() {
    char c = getchar();
    while ((c < 'a' || c > 'b') && (c < 'A' || c > 'Z')) c = getchar();
    while ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) return c;
    return c;
}
int n, m;
struct zzz {
    int tot, hp, dis, id;  // 手牌数量  血量  距离  身份:1=mp 2=zp 3=fp
    bool lfz, zgln, wszd, dead, one; // 类反猪标志  诸葛连弩  表明身份  死亡 杀只能用一次
    char  cord[2010]; // 手牌
}pig[110];
char allc[2010]; int pos;
int fp_num;
void mopai(int num, int k) {
    int &tot = pig[num].tot;
    for(int i = 1; i <= k; ++i) {
        if(pos == m) --pos;
        pig[num].cord[++tot] = allc[++pos];
    }
}
bool waf(int x, int y) {  // 判断x是否会对y献殷勤
    zzz &px = pig[x], &py = pig[y];
    if(py.wszd && (px.id == py.id || (px.id == 2 && py.id == 1) || (px.id == 1 && py.id == 2))) return 1;
    return 0;
}
bool godie(int x, int y){ //  判断x是否会对y表敌意
    zzz &px = pig[x], &py = pig[y];
    if(py.wszd && (px.id == 2 || px.id == 1) && py.id == 3) return 1;
    if(py.wszd && px.id == 3 && (py.id == 1 || py.id == 2)) return 1;
    if(py.lfz && px.id == 1) return 1;
    return 0;
}
bool wxkj(int num, int k, int lx) {
    for(int i = num, ii = 1; ii <= n; i = i%n+1, ++ii) {
        if(!lx && waf(i, k)) {
            for(int j = 1; j <= pig[i].tot; ++j) {
                if(pig[i].cord[j] == 'J') {
                    printf("玩家%d使用了无懈可击\n" ,i);
                    pig[i].wszd = 1, pig[i].cord[j] = '*', pig[i].lfz = 0;
                    //if(pig[2].wszd) printf("2号猪暴露身份\n\n");
                    int cnt = i%n+1;
                    if(wxkj(cnt, k, lx^1)) return 0; else return 1;
                }
            }
        }
        if(lx && godie(i, k)) {
            for(int j = 1; j <= pig[i].tot; ++j) {
                if(pig[i].cord[j] == 'J') {
                    printf("玩家%d使用了无懈可击\n" ,i);
                    pig[i].wszd = 1, pig[i].cord[j] = '*', pig[i].lfz = 0;
                    int cnt = i%n+1;
                    if(wxkj(cnt, k, lx^1)) return 0; else return 1;
                }
            }
        }

    }
    return 0;
}
void gameover(int flag) {
    printf("游戏结束\n");
    if(flag == 1) puts("MP");
    else puts("FP");
    for(int i = 1; i <= n; ++i) {
        if(pig[i].dead) {
            puts("DEAD"); continue;
        }
        for(int j = 1; j <= pig[i].tot; ++j) {
            if(pig[i].cord[j] != '*') printf("%c ", pig[i].cord[j]);
        }
        printf("\n");
    }
    exit(0);
}
void die(int num, int vic) { // num 伤害来源, vic 濒死
    zzz &p = pig[vic];
    for(int i = 1; i <= p.tot; ++i) {
        if(p.cord[i] == 'P') {
            printf("玩家%d对自己使用了桃,回复了一滴血\n", vic);
            p.cord[i] = '*', ++p.hp; return ;
        }
    }
    printf("玩家%d死亡,击杀者为玩家%d\n", vic, num);
    p.dead = 1;
    for(int i = 1; i <= p.tot; ++i) p.cord[i] = '*';
    if(p.id == 1) gameover(2); // 反猪胜利
    if(p.id == 3) {
        --fp_num; if(!fp_num) gameover(1); //主猪胜利
        mopai(num, 3);
        printf("玩家%d杀死了反贼,抽三张牌\n",num);
    }
    if(p.id == 2 && pig[num].id == 1) {
        for(int i = 1; i <= pig[num].tot; ++i)
            pig[num].cord[i] = '*';
        pig[num].zgln = 0;
        printf("主公杀死了忠臣,弃掉所有手牌\n");
    }
    int ff = 0, fff = 0;
    for(int i = n; i >= 1; --i) {
        if(!pig[i].dead) pig[i].dis = ff;
        if(!fff && !pig[i].dead) fff = i;
        ff = i;
    }
    pig[fff].dis = 1;
}
bool jd(int x, int y) {
    zzz &px = pig[x], &py = pig[y];
    int xx = 0, yy = 0;
    for(int i = 1; i <= px.tot; ++i)
        if(px.cord[i] == 'K') ++xx;
    for(int i = 1; i <= py.tot; ++i)
        if(py.cord[i] == 'K') ++yy;
    if(xx >= yy) {
        for(int i = 1, num = 1; num <= yy; ++i)
            if(px.cord[i] == 'K') px.cord[i] ='*', ++num;
        for(int i = 1, num = 1; num <= yy; ++i)
            if(py.cord[i] == 'K') py.cord[i] ='*', ++num;
        return 1;
    }
    else {
        for(int i = 1, num = 1; num <= xx; ++i)
            if(px.cord[i] == 'K') px.cord[i] ='*', ++num;
        for(int i = 1, num = 1; num <= xx+1; ++i)
            if(py.cord[i] == 'K') py.cord[i] ='*', ++num;
        return 0;
    }
}
bool chupai(int num) {
    zzz &p = pig[num];
    //if(p.cord[p.pos] == '*') ++p.pos;
    for(int l = 1; l <= p.tot; ++l) {
        if(p.cord[l] == 'Z') {
            printf("玩家%d装备了诸葛连弩\n", num);
            p.cord[l] = '*', p.zgln = 1; return 1;
        }
        if(p.cord[l] == 'P' && p.hp < 4) {
            printf("玩家%d 对自己使用了桃 ,现在剩余体力值为%d点\n ", num, pig[num].hp);
            p.cord[l] = '*', ++p.hp; return 1;
        }
        // W N 联动
        if(p.cord[l] == 'N') {
            printf("玩家%d对全体玩家使用了南蛮入侵\n", num);
            int cnt = num % n + 1; p.cord[l] = '*';
            for(int i = cnt; i != num; i = i%n+1) {
                if(pig[i].dead) continue; bool flag = 0;

                if(pig[i].wszd)  // 只能对跳身份的人献殷勤
                    if(wxkj(num, i, 0)) flag = 1;
                if(flag) continue;
                else printf("没有人对玩家%d使用无懈可击\n", i);

                for(int j = 1; j <= pig[i].tot; ++j) {
                    if(pig[i].cord[j] == 'K') {
                        printf("玩家%d使用了一张杀\n", i);
                        pig[i].cord[j] = '*', flag = 1; break;
                    }
                }
                if(!flag) {
                    printf("玩家%d失去了一点体力\n", i);
                    --pig[i].hp;
                    if(pig[i].hp) printf("玩家%d的血量是 %d\n", i, pig[i].hp);
                    if(i == 1 && !p.wszd) p.lfz = 1;
                }
                if(!pig[i].hp) die(num, i);
            }
            return 1;
        }
        if(p.cord[l] == 'W') {
            printf("玩家%d对全体玩家使用了万箭齐发\n", num);
            int cnt = num % n + 1; p.cord[l] = '*';
            for(int i = cnt; i != num; i = i%n+1) {
                if(pig[i].dead) continue;
                bool flag = 0;

                if(pig[i].wszd)  // 只能对跳身份的人献殷勤
                    if(wxkj(num, i, 0)) flag = 1;
                if(flag) continue;
                else printf("没有人对玩家%d使用无懈可击\n", i);

                for(int j = 1; j <= pig[i].tot; ++j) {
                    if(pig[i].cord[j] == 'D') {
                        printf("玩家%d使用了一张闪\n", i);
                        pig[i].cord[j] = '*', flag = 1; break;
                    }
                }
                if(!flag) {
                    printf("玩家%d失去了一点体力\n", i);
                    --pig[i].hp;
                    if(pig[i].hp) printf("玩家%d的血量是 %d\n", i, pig[i].hp);
                    if(i == 1 && !p.wszd) p.lfz = 1;
                }
                if(!pig[i].hp) die(num, i);
            }
            return 1;
        }

        if(p.cord[l] == 'K') {
            if(p.one && !p.zgln) return 0;
            bool flag = 0;
            int i = p.dis;
            if(!pig[i].dead && godie(num, i)) {
                printf("玩家%d对玩家%d使用了一张杀\n", num, i);
                p.cord[l] = '*'; p.wszd = 1; p.one = 1; p.lfz = 0;
                for(int j = 1; j <= pig[i].tot; ++j) {
                    if(pig[i].cord[j] == 'D') {
                        printf("玩家%d使用了一张闪\n", i);
                        pig[i].cord[j] = '*', flag = 1; break;
                    }
                }
                if(!flag) printf("玩家%d 受到了来自 玩家%d的杀的伤害\n", i, num), --pig[i].hp;
                if(pig[i].hp) printf("玩家%d的血量是 %d\n", i, pig[i].hp);
                if(!pig[i].hp) die(num, i);
                return 1;
                break;
            }
        }

        if(p.cord[l] == 'F') {
            int cnt = num % n + 1;
            if(p.id == 3) {
                int i = 1;
                printf("玩家%d对玩家%d使用了一张决斗\n", num, i);
                p.cord[l] = '*'; p.wszd = 1; p.lfz = 0;
                if(pig[i].wszd && wxkj(num, i, 0)) break;
                if(p.id == 1 && pig[i].lfz == 1 && pig[i].id == 2) {
                    printf("玩家%d决斗失败,失去一点血\n", i); --pig[i].hp; goto ree;
                }
                if(jd(num, i)) --pig[i].hp, printf("玩家%d决斗失败,失去一点血\n",i);
                else --pig[num].hp, printf("玩家%d决斗失败,失去一点血\n", num);
                ree:
                if(pig[num].hp) printf("玩家%d的血量是 %d\n", num,pig[num].hp);
                if(pig[i].hp) printf("玩家%d的血量是 %d\n", i,pig[i].hp);

                if(!pig[i].hp) die(num, i);
                if(!pig[num].hp) die(i, num);
                return 1;
            }
            for(int i = cnt; i != num; i = i%n+1) {
                if(!pig[i].dead && godie(num, i)) {
                    printf("玩家%d对玩家%d使用了一张决斗\n", num, i);
                    p.cord[l] = '*'; p.wszd = 1; p.lfz = 0;
                    if(wxkj(num, i, 0)) break;
                    if(p.id == 1 && pig[i].lfz == 1 && pig[i].id == 2) {
                        printf("玩家%d决斗失败,失去一点血\n", i);
                        --pig[i].hp; goto re;
                    }
                    if(jd(num, i)) --pig[i].hp, printf("玩家%d决斗失败,失去一点血\n",i);
                    else --pig[num].hp, printf("玩家%d决斗失败,失去一点血\n", num);
                    re:
                    if(pig[num].hp) printf("玩家%d的血量是 %d\n", num,pig[num].hp);
                    if(pig[i].hp) printf("玩家%d的血量是 %d\n", i,pig[i].hp);

                    if(!pig[i].hp) die(num, i);
                    if(!pig[num].hp) die(i, num);
                    return 1;
                }
            }
        }
    }
    return 0;
}
int main() {
    freopen("1.in", "r", stdin);
    freopen("my.out", "w", stdout);
    n = read(), m = read();
    for(int i = 1; i <= n; ++i) {
        char c[3]; cin >> c;
        pig[i].hp = pig[i].tot = 4;
        if(c[0] == 'M') pig[i].id = 1;
        if(c[0] == 'Z') pig[i].id = 2;
        if(c[0] == 'F') pig[i].id = 3, ++fp_num;
        for(int j = 1; j <= 4; ++j) pig[i].cord[j] = read_c();
        pig[i].dis = i % n + 1;
    }
    pig[1].wszd = 1;
    for(int i = 1; i <= m; ++i) allc[i] = read_c();
    int cnt = 0, tot = 0;
    while(1) {
        cnt = cnt % n + 1;  zzz &p = pig[cnt];
        if(p.dead) continue;
        mopai(cnt, 2);
        while(chupai(cnt)) {}
        p.one = 0;
        printf("回合%d结束\n", ++tot); printf("\n----------------------\n\n");
    }
    return 0;
}

AC代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#define LL long long
using namespace std;
LL read() {
    LL k = 0, f = 1; char c = getchar();
    while(c < '0' || c > '9') {
        if(c == '-') f = -1;
        c = getchar();
    }
    while(c >= '0' && c <= '9')
      k = k * 10 + c - 48, c = getchar();
    return k * f;
}
char read_c() {
    char c = getchar();
    while ((c < 'a' || c > 'b') && (c < 'A' || c > 'Z')) c = getchar();
    while ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) return c;
    return c;
}
int n, m;
struct zzz {
    int tot, hp, dis, id;  // 手牌数量  血量  距离  身份:1=mp 2=zp 3=fp
    bool lfz, zgln, wszd, dead, one; // 类反猪标志  诸葛连弩  表明身份  死亡 杀只能用一次
    char  cord[2010]; // 手牌
}pig[110];
char allc[2010]; int pos;
int fp_num;
void mopai(int num, int k) {
    int &tot = pig[num].tot;
    for(int i = 1; i <= k; ++i) {
        if(pos == m) --pos;
        pig[num].cord[++tot] = allc[++pos];
    }
}
bool waf(int x, int y) {  // 判断x是否会对y献殷勤
    zzz &px = pig[x], &py = pig[y];
    if(py.wszd && (px.id == py.id || (px.id == 2 && py.id == 1) || (px.id == 1 && py.id == 2))) return 1;
    return 0;
}
bool godie(int x, int y){ //  判断x是否会对y表敌意
    zzz &px = pig[x], &py = pig[y];
    if(py.wszd && (px.id == 2 || px.id == 1) && py.id == 3) return 1;
    if(py.wszd && px.id == 3 && (py.id == 1 || py.id == 2)) return 1;
    if(py.lfz && px.id == 1) return 1;
    return 0;
}
bool wxkj(int num, int k, int lx) {
    for(int i = num, ii = 1; ii <= n; i = i%n+1, ++ii) {
        if(!lx && waf(i, k)) {
            for(int j = 1; j <= pig[i].tot; ++j) {
                if(pig[i].cord[j] == 'J') {
                    pig[i].wszd = 1, pig[i].cord[j] = '*', pig[i].lfz = 0;
                    int cnt = i%n+1;
                    if(wxkj(cnt, k, lx^1)) return 0; else return 1;
                }
            }
        }
        if(lx && godie(i, k)) {
            for(int j = 1; j <= pig[i].tot; ++j) {
                if(pig[i].cord[j] == 'J') {
                    pig[i].wszd = 1, pig[i].cord[j] = '*', pig[i].lfz = 0;
                    int cnt = i%n+1;
                    if(wxkj(cnt, k, lx^1)) return 0; else return 1;
                }
            }
        }

    }
    return 0;
}
void gameover(int flag) {
    if(flag == 1) puts("MP");
    else puts("FP");
    for(int i = 1; i <= n; ++i) {
        if(pig[i].dead) {
            puts("DEAD"); continue;
        }
        for(int j = 1; j <= pig[i].tot; ++j) {
            if(pig[i].cord[j] != '*') printf("%c ", pig[i].cord[j]);
        }
        printf("\n");
    }
    exit(0);
}
void die(int num, int vic) { // num 伤害来源, vic 濒死
    zzz &p = pig[vic];
    for(int i = 1; i <= p.tot; ++i) {
        if(p.cord[i] == 'P') {
            p.cord[i] = '*', ++p.hp; return ;
        }
    }
    p.dead = 1;
    for(int i = 1; i <= p.tot; ++i) p.cord[i] = '*';
    if(p.id == 1) gameover(2); // 反猪胜利
    if(p.id == 3) {
        --fp_num; if(!fp_num) gameover(1); //主猪胜利
        mopai(num, 3);
    }
    if(p.id == 2 && pig[num].id == 1) {
        for(int i = 1; i <= pig[num].tot; ++i)
            pig[num].cord[i] = '*';
        pig[num].zgln = 0;
    }
    int ff = 0, fff = 0;
    for(int i = n; i >= 1; --i) {
        if(!pig[i].dead) pig[i].dis = ff;
        if(!fff && !pig[i].dead) fff = i;
        ff = i;
    }
    pig[fff].dis = 1;
}
bool jd(int x, int y) {
    zzz &px = pig[x], &py = pig[y];
    int xx = 0, yy = 0;
    for(int i = 1; i <= px.tot; ++i)
        if(px.cord[i] == 'K') ++xx;
    for(int i = 1; i <= py.tot; ++i)
        if(py.cord[i] == 'K') ++yy;
    if(xx >= yy) {
        for(int i = 1, num = 1; num <= yy; ++i)
            if(px.cord[i] == 'K') px.cord[i] ='*', ++num;
        for(int i = 1, num = 1; num <= yy; ++i)
            if(py.cord[i] == 'K') py.cord[i] ='*', ++num;
        return 1;
    }
    else {
        for(int i = 1, num = 1; num <= xx; ++i)
            if(px.cord[i] == 'K') px.cord[i] ='*', ++num;
        for(int i = 1, num = 1; num <= xx+1; ++i)
            if(py.cord[i] == 'K') py.cord[i] ='*', ++num;
        return 0;
    }
}
bool chupai(int num) {
    zzz &p = pig[num];
    //if(p.cord[p.pos] == '*') ++p.pos;
    for(int l = 1; l <= p.tot; ++l) {
        if(p.cord[l] == 'Z') {
            p.cord[l] = '*', p.zgln = 1; return 1;
        }
        if(p.cord[l] == 'P' && p.hp < 4) {
            p.cord[l] = '*', ++p.hp; return 1;
        }
        // W N 联动
        if(p.cord[l] == 'N') {
            int cnt = num % n + 1; p.cord[l] = '*';
            for(int i = cnt; i != num; i = i%n+1) {
                if(pig[i].dead) continue; bool flag = 0;

                if(pig[i].wszd)  // 只能对跳身份的人献殷勤
                    if(wxkj(num, i, 0)) flag = 1;
                if(flag) continue;

                for(int j = 1; j <= pig[i].tot; ++j) {
                    if(pig[i].cord[j] == 'K') {
                        pig[i].cord[j] = '*', flag = 1; break;
                    }
                }
                if(!flag) {
                    --pig[i].hp;
                    if(i == 1 && !p.wszd) p.lfz = 1;
                }
                if(!pig[i].hp) die(num, i);
            }
            return 1;
        }
        if(p.cord[l] == 'W') {
            int cnt = num % n + 1; p.cord[l] = '*';
            for(int i = cnt; i != num; i = i%n+1) {
                if(pig[i].dead) continue;
                bool flag = 0;

                if(pig[i].wszd)  // 只能对跳身份的人献殷勤
                    if(wxkj(num, i, 0)) flag = 1;
                if(flag) continue;

                for(int j = 1; j <= pig[i].tot; ++j) {
                    if(pig[i].cord[j] == 'D') {
                        pig[i].cord[j] = '*', flag = 1; break;
                    }
                }
                if(!flag) {
                    --pig[i].hp;
                    if(i == 1 && !p.wszd) p.lfz = 1;
                }
                if(!pig[i].hp) die(num, i);
            }
            return 1;
        }

        if(p.cord[l] == 'K') {
            if(p.one && !p.zgln) continue;
            bool flag = 0;
            int i = p.dis;
            if(!pig[i].dead && godie(num, i)) {
                p.cord[l] = '*'; p.wszd = 1; p.one = 1; p.lfz = 0;
                for(int j = 1; j <= pig[i].tot; ++j) {
                    if(pig[i].cord[j] == 'D') {
                        pig[i].cord[j] = '*', flag = 1; break;
                    }
                }
                if(!flag) --pig[i].hp;
                if(!pig[i].hp) die(num, i);
                return 1;
                break;
            }
        }

        if(p.cord[l] == 'F') {
            int cnt = num % n + 1;
            if(p.id == 3) {
                int i = 1;
                p.cord[l] = '*'; p.wszd = 1; p.lfz = 0;
                if(pig[i].wszd && wxkj(num, i, 0)) break;
                if(p.id == 1 && pig[i].lfz == 1 && pig[i].id == 2) {
                    --pig[i].hp; goto ree;
                }
                if(jd(num, i)) --pig[i].hp;
                else --pig[num].hp;
                ree:
                if(!pig[i].hp) die(num, i);
                if(!pig[num].hp) die(i, num);
                return 1;
            }
            for(int i = cnt; i != num; i = i%n+1) {
                if(!pig[i].dead && godie(num, i)) {
                    p.cord[l] = '*'; p.wszd = 1; p.lfz = 0;
                    if(wxkj(num, i, 0)) break;
                    if(p.id == 1 && pig[i].lfz == 1 && pig[i].id == 2) {
                        --pig[i].hp; goto re;
                    }
                    if(jd(num, i)) --pig[i].hp;
                    else --pig[num].hp;
                    re:
                    if(!pig[i].hp) die(num, i);
                    if(!pig[num].hp) die(i, num);
                    return 1;
                }
            }
        }
    }
    return 0;
}
int main() {
    n = read(), m = read();
    for(int i = 1; i <= n; ++i) {
        char c[3]; cin >> c;
        pig[i].hp = pig[i].tot = 4;
        if(c[0] == 'M') pig[i].id = 1;
        if(c[0] == 'Z') pig[i].id = 2;
        if(c[0] == 'F') pig[i].id = 3, ++fp_num;
        for(int j = 1; j <= 4; ++j) pig[i].cord[j] = read_c();
        pig[i].dis = i % n + 1;
    }
    pig[1].wszd = 1;
    for(int i = 1; i <= m; ++i) allc[i] = read_c();
    int cnt = 0;
    while(1) {
        cnt = cnt % n + 1;  zzz &p = pig[cnt];
        if(p.dead) continue;
        mopai(cnt, 2);
        while(chupai(cnt)) {}
        p.one = 0;
    }
    return 0;
}
01-14 15:59