#include using namespace std; int n, m; char js[15]; // 角色:M主猪, Z忠猪, F反猪 char p[15][10005]; // 手牌 int l[15], r[15]; // 手牌左右边界(闭区间) vector dui; // 牌堆(尾部为堆顶) int stre[15]; // 体力值 int fro[15], nex[15]; // 双向链表,用于存活角色遍历 bool zgln[15]; // 是否装备诸葛连弩 bool tiao[15]; // 是否已跳身份(忠/反表明) bool lei[15]; // 主猪的类反猪标记 char last_card = 'P'; // 牌堆最后一张(初始为桃,避免空堆摸到空字符) inline char read() { char ch = getchar(); while (ch < 'A' || ch > 'Z') ch = getchar(); return ch; } void init() { scanf("%d %d\n", &n, &m); for (int i = 0; i < n; ++i) { js[i] = read(); read(); // 跳过空格 for (int j = 0; j < 4; ++j) p[i][j] = read(); stre[i] = 4; l[i] = 0; r[i] = 3; fro[i] = (i == 0) ? (n - 1) : (i - 1); nex[i] = (i + 1) % n; } for (int i = 0; i < m; ++i) dui.push_back(read()); reverse(dui.begin(), dui.end()); // 牌堆尾部为堆顶 } int pd() { bool fp_alive = false; for (int i = 0; i < n; ++i) if (js[i] == 'F' && stre[i] > 0) { fp_alive = true; break; } if (stre[0] <= 0) return 2; // FP胜 if (!fp_alive) return 1; // MP胜 return 0; // 未结束 } void mp(int now, int cnt) { while (cnt--) { if (!dui.empty()) { last_card = dui.back(); dui.pop_back(); } p[now][++r[now]] = last_card; } } void dealdead(int now, int from) { // 濒死求桃 if (stre[now] <= 0) { for (int j = l[now]; j <= r[now]; ++j) if (p[now][j] == 'P') { stre[now]++; p[now][j] = 0; if (stre[now] > 0) break; } } if (stre[now] <= 0) { // 死亡处理:从存活链表中移除 if (now != 0) { nex[fro[now]] = nex[now]; fro[nex[now]] = fro[now]; } // 奖惩:仅在游戏未结束时执行 if (pd() == 0) { if (js[now] == 'F') { mp(from, 3); } else if (js[now] == 'Z' && js[from] == 'M') { // 主猪弃掉所有手牌和装备 for (int j = l[from]; j <= r[from]; ++j) p[from][j] = 0; l[from] = 0; r[from] = -1; zgln[from] = false; } } // 死亡猪自己的手牌全部弃置 for (int j = l[now]; j <= r[now]; ++j) p[now][j] = 0; l[now] = 0; r[now] = -1; zgln[now] = false; } } /* ---------- 无懈可击相关函数 ---------- */ int findJ(int now) { for (int i = l[now]; i <= r[now]; ++i) if (p[now][i] == 'J') return i; return -1; } void useJ(int now) { int pos = findJ(now); if (pos != -1) p[now][pos] = 0; } // 判断 now 是否会对 target 使用无懈可击,isProtect=true 表示献殷勤,false 表示表敌意 bool canUseJ(int now, int target, bool isProtect) { if (isProtect) { // 献殷勤:不会对未表明身份的猪(包括自己),主猪视为已表明 if (!(tiao[target] || js[target] == 'M')) return false; if (js[now] == 'M') return (target == now) || (js[target] == 'Z' && tiao[target]); else if (js[now] == 'Z') return (target == 0) || (js[target] == 'Z' && tiao[target]); else if (js[now] == 'F') return (js[target] == 'F' && tiao[target]); } else { // 表敌意 if (js[now] == 'M') return (js[target] == 'F' && tiao[target]); else if (js[now] == 'Z') return (js[target] == 'F' && tiao[target]); else if (js[now] == 'F') return (target == 0) || (js[target] == 'Z' && tiao[target]); } return false; } // 询问链:当前牌的使用者 user,目标 target,isProtect 表示当前牌是保护(true)还是攻击(false) // 返回 true 表示当前牌被无懈可击抵消 bool askWJ(int user, int target, bool isProtect) { if (pd() != 0) return false; int cur = user; do { if (stre[cur] <= 0) { cur = nex[cur]; continue; } if (findJ(cur) == -1) { cur = nex[cur]; continue; } bool willProtect; int jTarget; if (!isProtect) // 当前牌是攻击(锦囊),出J是保护 { willProtect = true; jTarget = target; } else // 当前牌是保护(J),出J是攻击 { willProtect = false; jTarget = user; } if (canUseJ(cur, jTarget, willProtect)) { useJ(cur); // 弃置最左的J // 跳身份处理 if (willProtect) // 献殷勤 { if (js[cur] == 'Z' && (jTarget == 0 || (js[jTarget] == 'Z' && tiao[jTarget]))) tiao[cur] = true, lei[cur] = false; else if (js[cur] == 'F' && (js[jTarget] == 'F' && tiao[jTarget])) tiao[cur] = true, lei[cur] = false; // 主猪献殷勤不需跳身份 } else // 表敌意 { if (js[cur] == 'Z' && js[jTarget] == 'F' && tiao[jTarget]) tiao[cur] = true, lei[cur] = false; else if (js[cur] == 'F' && (jTarget == 0 || (js[jTarget] == 'Z' && tiao[jTarget]))) tiao[cur] = true, lei[cur] = false; // 主猪表敌意给已跳反猪,若目标有类反标记则清除 if (js[cur] == 'M' && js[jTarget] == 'F' && tiao[jTarget]) lei[jTarget] = false; } // 递归:询问是否有人无懈可击这张J if (!askWJ(cur, jTarget, willProtect)) // 这张J没有被抵消 → 成功抵消当前牌 return true; // 否则J被抵消,继续循环询问下一个猪 } cur = nex[cur]; } while (cur != user); return false; } /* ---------- 锦囊结算 ---------- */ void NW(int now, char KD) // 南蛮/万箭 { int cur = nex[now]; while (cur != now) { if (stre[cur] <= 0) { cur = nex[cur]; continue; } // 无懈可击抵消此次范围伤害 if (askWJ(now, cur, false)) { cur = nex[cur]; continue; } bool kou = true; for (int j = l[cur]; j <= r[cur]; ++j) if (p[cur][j] == KD) { p[cur][j] = 0; kou = false; break; } if (kou) { stre[cur]--; if (cur == 0 && !tiao[now]) lei[now] = 1; dealdead(cur, now); if (pd()) return; } cur = nex[cur]; } } void do_K(int now, int obj) { // 跳身份 if (js[now] == 'Z' && js[obj] == 'F' && tiao[obj]) tiao[now] = true, lei[now] = false; if (js[now] == 'F' && (js[obj] == 'M' || (js[obj] == 'Z' && tiao[obj]))) tiao[now] = true, lei[now] = false; bool kou = true; for (int i = l[obj]; i <= r[obj]; ++i) if (p[obj][i] == 'D') { p[obj][i] = 0; kou = false; break; } if (kou) { stre[obj]--; dealdead(obj, now); } } bool haveK(int now) { for (int i = l[now]; i <= r[now]; ++i) if (p[now][i] == 'K') { p[now][i] = 0; return true; } return false; } void do_F(int now, int obj) { // 跳身份 if (js[now] == 'Z' && js[obj] == 'F' && tiao[obj]) tiao[now] = true, lei[now] = false; if (js[now] == 'F' && (js[obj] == 'M' || (js[obj] == 'Z' && tiao[obj]))) tiao[now] = true, lei[now] = false; // 无懈可击抵消决斗 if (askWJ(now, obj, false)) return; // 决斗无效 bool turn = false; // false=obj先出杀 while (true) { int cur = turn ? now : obj; int opp = turn ? obj : now; if (js[cur] == 'Z' && js[opp] == 'M') break; if (haveK(cur)) turn = !turn; else break; } if (turn) { stre[now]--; dealdead(now, obj); } else { stre[obj]--; dealdead(obj, now); } } void cp(int now) { bool usedK = false; int F_target = -1; while (pd() == 0 && stre[now] > 0) { int pos = -1; for (int i = l[now]; i <= r[now]; ++i) { if (p[now][i] == 0) continue; char c = p[now][i]; if (c == 'P' && stre[now] < 4) { pos = i; break; } if (c == 'Z') { pos = i; break; } if (c == 'N' || c == 'W') { pos = i; break; } if (c == 'K') { int obj = nex[now]; if (stre[obj] > 0) { bool ok = false; if (js[now] == 'M') ok = (js[obj] == 'F' && tiao[obj]) || (!tiao[obj] && lei[obj]); else if (js[now] == 'Z') ok = (js[obj] == 'F' && tiao[obj]); else if (js[now] == 'F') ok = (obj == 0) || (js[obj] == 'Z' && tiao[obj]); if (ok && (!usedK || zgln[now])) { pos = i; break; } } } if (c == 'F') { int obj = -1; if (js[now] == 'M') { for (int j = nex[now]; j != now; j = nex[j]) { if (stre[j] <= 0) continue; if ((js[j] == 'F' && tiao[j]) || (!tiao[j] && lei[j])) { obj = j; break; } } } else if (js[now] == 'Z') { for (int j = nex[now]; j != now; j = nex[j]) { if (stre[j] <= 0) continue; if (js[j] == 'F' && tiao[j]) { obj = j; break; } } } else if (js[now] == 'F') { if (stre[0] > 0) obj = 0; else { for (int j = nex[now]; j != now; j = nex[j]) { if (stre[j] <= 0) continue; if (js[j] == 'M' || (js[j] == 'Z' && tiao[j])) { obj = j; break; } } } } if (obj != -1) { pos = i; F_target = obj; // 保存目标 break; } } // 跳过 J(无懈可击不能主动使用) } if (pos == -1) break; char card = p[now][pos]; p[now][pos] = 0; if (card == 'P') { stre[now]++; } else if (card == 'Z') { zgln[now] = true; } else if (card == 'N') { NW(now, 'K'); if (pd()) break; } else if (card == 'W') { NW(now, 'D'); if (pd()) break; } else if (card == 'K') { do_K(now, nex[now]); usedK = true; if (pd()) break; } else if (card == 'F') { if (F_target != -1 && stre[F_target] > 0) { do_F(now, F_target); if (pd()) break; } F_target = -1; } } } int main() { init(); for (int i = 0; pd() == 0; i = nex[i]) { if (stre[i] <= 0) continue; mp(i, 2); cp(i); } printf("%s\n", pd() == 1 ? "MP" : "FP"); for (int i = 0; i < n; ++i) { if (stre[i] <= 0) printf("DEAD\n"); else { bool first = true; for (int j = l[i]; j <= r[i]; ++j) if (p[i][j] != 0) { if (!first) printf(" "); printf("%c", p[i][j]); first = false; } printf("\n"); } } return 0; }