求调大模拟 RE+TLE 0pts,有详尽注释

P2482 [SDOI2010] 猪国杀

代码更新: ```cpp #include <bits/stdc++.h> #include <bits/extc++.h> #define DEBUG std::cerr<<"This task has passed.\n" //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 == 0)result = "MP", 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; } ```
by __er @ 2023-07-25 16:03:20


|