求调大模拟 RE+TLE 0pts,有详尽注释
查看原帖
求调大模拟 RE+TLE 0pts,有详尽注释
713955
__er楼主2023/7/25 14:44
#include <bits/stdc++.h>
#include <bits/extc++.h>
//Day0缺省源/oh
//Day1.1 整理题意:
/*
角色:
    MP:主公,杀死所有 FP
    ZP:忠臣,保护 MP
    FP:反贼,杀死 MP
手牌:
    普通:
        P/桃:体力+1
        K/杀:攻击范围内,目标不弃置 闪/D 目标体力-1
        D/闪:被 K/杀 选定为目标,弃置避免受到伤害
    锦囊:
        F/决斗:目标角色开始,轮流弃置 K/杀,最先无 K/杀 可弃置的角色体力 -1
        N/南蛮入侵:逆时针顺序每人弃置一张 K/杀 或体力-1
        W/万箭齐发:逆时针顺序每人弃置一张 D/闪 或体力-1
        J/无懈可击:抵消一未生效的锦囊牌的效果
    装备:
        Z/诸葛连弩:攻击范围 1,出牌阶段使用 K/杀 无限制
规则:
    距离:逆时针方向间隔的玩家数+1
    奖励:FP 死亡时,造成致命一击的玩家立即摸三张牌
    惩罚:若 MP 杀死 ZP,弃置其所有手牌
    行为规范:ZP 不跳反,FP 不跳忠,无论 ZP/FP 能跳必然跳
行为:
    献殷勤:使用 J/无懈可击 抵消对目标造成伤害的行为(包括表敌意),称对目标献殷勤
    表敌意:使用 J/无懈可击 抵消目标对其目标献殷勤献殷勤或对攻击目标(使用 K/杀 或 F/决斗),称对目标献殷勤
    跳忠:对跳忠过的玩家献殷勤或对跳反过的玩家表敌意
    跳反:对跳反过的玩家献殷勤或对跳忠过的玩家表敌意
行动准则:
    共性:有手牌可用必然用,不对未标明身份的玩家献殷勤,**包括自己!**
    特性
        MP:
            1.未跳忠/跳反,对 MP 造成伤害,MP 认为其是 类FP
            2.逆时针表敌意目标满足是 FP 或 类FP
            3.尽可能对 ZP 献殷勤,对 FP 表敌意(已经跳忠/反的
        ZP:
            1.逆时针表敌意目标满足是 FP
            2.决斗时对方是 MP 则不弃置 K/杀
            3.尽可能对 MP 和 ZP 献殷勤
        FP:
            1.表敌意优先对 MP 表,如果不行对逆时针第一只 ZP 表
            2.尽可能对 FP 献殷勤
终于写完了(
*/
#define unknown 0//布吉岛
#define TZ 1//跳过忠
#define TF 2//跳过反
#define LF 3//类FP
#define MP 4//MP
struct pig {
    int hp/*血量*/, Kcnt, Dcnt, Pcnt, Jcnt, nxt, pre/*前后猪*/, glbid/*全局身份*/, Ktarget, Ftarget/*杀和决斗的指定猪*/;
    bool isalive, isweapon;/*是否活着/装备武器*/
    std::string id;//身份
    std::vector<char> card;//手牌
} pigs[11];
std::queue<char> cards; //牌堆,牌堆空默认摸最后一张牌!
int pigcnt, fpcnt, cardscnt, ptr; //猪计数,反猪计数和手牌计数
std::string result;//结果:MP/FP
void fold(int target, char card) {
    pigs[target].card.erase(std::find(pigs[target].card.begin(), pigs[target].card.end(), card));
}
void getcardformcards(int times, int target) { //target 摸牌 times 次
    while (times--) {
        pigs[target].card.push_back(cards.front());
        //更新计数器
        if (cards.front() == 'D')pigs[target].Dcnt++;
        if (cards.front() == 'K')pigs[target].Kcnt++;
        if (cards.front() == 'P')pigs[target].Pcnt++;
        if (cards.front() == 'J')pigs[target].Jcnt++;
        if (cards.size() > 1)cards.pop();
    }
}
void initcards(int target) { //初始化 target 的 4 张手牌
    char tmp;
    for (int t = 1; t <= 4; t++) {
        //更新计数器
        std::cin >> tmp, pigs[target].card.push_back(tmp);
        if (tmp == 'D')pigs[target].Dcnt++;
        if (tmp == 'K')pigs[target].Kcnt++;
        if (tmp == 'P')pigs[target].Pcnt++;
        if (tmp == 'J')pigs[target].Jcnt++;
    }
}
void outputresult() {
    std::cout << result << '\n';//输出结果
    for (int i = 1; i <= pigcnt; i++) {
        if (!pigs[i].isalive)std::cout << "DEAD";
        else if (!pigs[i].card.empty())for (auto i : pigs[i].card)std::cout << i << " ";
        std::cout << "\n";
    }
}
void clearcard(int target) { //target 弃掉所有手牌
    pigs[target].isweapon = false, pigs[target].Dcnt = pigs[target].Kcnt = pigs[target].Pcnt = pigs[target].Jcnt = 0;
    pigs[target].card.clear();
}
void havebeendead(int target) { //target 似了
    pigs[target].isalive = false, clearcard(target);
    pigs[pigs[target].nxt].pre = pigs[target].pre, pigs[pigs[target].pre].nxt = pigs[target].nxt;
    if (pigs[target].id == "MP") result = "FP", outputresult(), exit(0); //MP 似了,结束
    if (pigs[target].id == "FP" && --fpcnt == 1)outputresult(), exit(0); //FP 似完了,结束
}
void dying(int pigx, int target) {
    if (pigs[target].Pcnt)pigs[target].Pcnt--, fold(target, 'P'), pigs[target].hp++;
    else {//没有桃为自己恢复
        havebeendead(target);//你似拉!!!
        if (pigs[pigx].id == "MP" && pigs[target].id == "ZP")clearcard(pigx);
        else if (pigs[target].id == "FP")getcardformcards(3, pigx);
    }
}
void K(int pigx, int target) {//pigx 使用 杀 指向 target
    if (pigs[pigx].glbid == unknown || pigs[pigx].glbid == LF)pigs[pigx].glbid = pigs[target].glbid == TZ ? TF : TZ;//处理身份
    if (pigs[target].Dcnt)pigs[target].Dcnt--, fold(target, 'D'); //有闪则弃
    else if (--pigs[target].hp <= 0)dying(pigx, target);//濒死状态
}
void init(int target) { //对 target 初始化
    std::string type;
    std::cin >> type;//更新身份
    if (type == "MP")pigs[target].id = "MP", pigs[target].glbid = MP;
    if (type == "ZP")pigs[target].id = "ZP";
    if (type == "FP")pigs[target].id = "FP", fpcnt++, pigs[target].Ktarget = 1;
    initcards(target); //摸四张牌
    pigs[target].hp = 4, pigs[target].isalive = true;
    if (target == 1)pigs[target].nxt = 2, pigs[target].pre = pigcnt;
    if (target == pigcnt)pigs[target].nxt = 1, pigs[target].pre = pigcnt - 1;
    pigs[target].nxt = target + 1, pigs[target].pre = target - 1;//更新前后猪
}
bool isover() {//判断游戏是否结束
    if (pigs[1].isalive = false) {result = "FP"; return true;}
    if (fpcnt == 0) {result = "MP"; return true;}
    return false;
}
int gettarget(int target, std::string type) {//判断 target 的 nxt猪 是否能作为 target 杀的目标,是则返回 nxt 猪,否则 0
    if (type == "MP")return (pigs[pigs[target].nxt].glbid == TF || pigs[pigs[target].nxt].glbid == LF ? pigs[target].nxt : 0);
    if (type == "ZP")return (pigs[pigs[target].nxt].glbid == TF ? pigs[target].nxt : 0);
    if (type == "FP")return (pigs[pigs[target].nxt].glbid == TZ ? pigs[target].nxt : 0);
}
void updateK(int target) {//更新 target 的杀的目标猪
    if (pigs[target].id == "MP")pigs[target].Ktarget = gettarget(target, "MP");
    if (pigs[target].id == "ZP")pigs[target].Ktarget = gettarget(target, "ZP");
    if (pigs[target].id == "FP")pigs[target].Ktarget = gettarget(target, "FP");
}
bool checkFtarget(int from, int to) {//判断 from 是否可以指定 to 为决斗的目标
    return ((from == 1 && (pigs[to].glbid = TF || pigs[to].glbid == LF)) || (pigs[from].glbid == TZ && pigs[to].glbid == TF));
}
void updateF(int target) {//更新 target 的决斗的目标猪
    for (int i = pigs[target].nxt; i != target; i = pigs[i].nxt)if (checkFtarget(target, i))return void(pigs[target].Ftarget = i);
    return void(pigs[target].Ftarget = 0);
}
bool askforJtoprotect(int pigx, int ident) {//无懈可击
    if (ident == unknown || ident == LF)return false;
    for (int i = pigx; i; i = pigs[i].nxt) {
        if (pigs[i].Jcnt) {//有无懈可击
            if (ident == TZ && (pigs[i].id == "MP" || pigs[i].id == "ZP")) {
                fold(i, 'J'), pigs[i].Jcnt--;//弃掉
                if (pigs[i].glbid == unknown || pigs[i].glbid == LF/*不知道身份会更新,如果是类反猪,主猪会重新认识这只猪*/)pigs[i].glbid = TZ;
                return !askforJtoprotect(i, TF);//如果跳过反的猪使用了无懈可击抵消这张无懈可击,则返回与之相反的结果
            } else if (ident == TF && pigs[i].id == "FP") { //如果是跳过反的猪,反猪会帮它
                fold(i, 'J'), pigs[i].Jcnt--;//弃掉
                if (pigs[i].glbid == unknown || pigs[i].glbid == LF)pigs[i].glbid = TF;//反猪身份确定
                return askforJtoprotect(i, TZ);//同上
            }
            if (i == pigs[pigx].pre)return false; //已经转了一圈了,停
        }
    }
}
void F(int pigx, int target) { //pigx 向 target 决斗!
    if (pigs[pigx].glbid == unknown || pigs[pigx].glbid == LF)pigs[pigx].glbid = (pigs[target].glbid == TZ ? TF : TZ);
    if (askforJtoprotect(pigx, pigs[target].glbid))return;
    if (pigs[pigx].id == "MP" && pigs[target].id == "ZP") { //MP F=> ZP,ZP 只得掉血
        if (--pigs[target].hp <= 0)dying(pigx, target);
        return;
    }
    int pointer = target; // pointer 指向的猪需要弃置一张 K;
    while (pigs[pointer].Kcnt)/*pointer 指向的猪猪还有杀杀*/fold(pointer, 'K'), pigs[pointer].Kcnt--, pointer = (pointer == pigx ? target : pigx);
    if (--pigs[pointer].hp <= 0)dying((pointer == target ? pigx : target), pointer);
}
void N_W(int pigx, char type) { //pigx 发动南蛮入侵/万箭齐发(由第二个参数决定)
    for (int i = pigs[pigx].nxt; i != pigx; i = pigs[i].nxt) {
        if (!askforJtoprotect(pigx, pigs[i].glbid)) {
            if (type == 'N') {
                if (pigs[i].Kcnt)fold(i, 'K'), pigs[i].Kcnt--;//南蛮入侵弃 K
                if (pigs[i].id == "MP" && pigs[pigx].glbid == unknown)pigs[pigx].glbid = LF;
                else if (--pigs[i].hp <= 0)dying(pigx, i);
            }
            if (type == 'W') {
                if (pigs[i].Kcnt)fold(i, 'D'), pigs[i].Kcnt--;//万箭齐发弃 D
                if (pigs[i].id == "MP" && pigs[pigx].glbid == unknown)pigs[pigx].glbid = LF;
                else if (--pigs[i].hp <= 0)dying(pigx, i);
            }
        }
    }
}
void sol(int target) { //就决定是 target 辣!
    getcardformcards(2, target);
    int usedKtimes = 0; //用过杀的次数
    for (int idx = 0; idx < pigs[target].card.size(); idx++) {
        char i = pigs[target].card[idx];
        if (i == 'Z')fold(target, 'Z'), pigs[target].isweapon = true, idx = 0;
        if (i == 'F') {
            if (pigs[target].id != "FP")updateF(target);
            if (pigs[target].Ftarget != 0)fold(target, 'F'), F(target, pigs[target].Ftarget);
            if (!pigs[target].isalive)return;
        }
        if (i == 'K' && (usedKtimes == 0 || pigs[target].isweapon))updateK(target), fold(target, 'K'), K(target, pigs[target].Ktarget), usedKtimes++, pigs[target].Kcnt--, idx = 0;
        if (i == 'P' && pigs[target].hp < 4)fold(target, 'P'), pigs[target].Pcnt--, pigs[target].hp++, idx--;
        if (i == 'N')fold(target, 'N'), N_W(target, 'N'), idx = 0;
        if (i == 'W')fold(target, 'W'), N_W(target, 'W'), idx = 0;
    }
}
char c;
signed main() {
    std::ios::sync_with_stdio(false), std::cin.tie(nullptr), std::cout.tie(nullptr);
    std::cin >> pigcnt >> cardscnt, ptr = 1;
    for (int i = 1; i <= pigcnt; i++)init(i);
    while (cardscnt--)std::cin >> c, cards.push(c);
    while (!isover())sol(ptr), ptr = pigs[ptr].nxt;
    return outputresult(), 0;
}
2023/7/25 14:44
加载中...