new file: P2482.cpp
This commit is contained in:
@@ -0,0 +1,478 @@
|
|||||||
|
#include <bits/stdc++.h>
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
int n, m;
|
||||||
|
char js[15]; // 角色:M主猪, Z忠猪, F反猪
|
||||||
|
char p[15][10005]; // 手牌
|
||||||
|
int l[15], r[15]; // 手牌左右边界(闭区间)
|
||||||
|
vector<char> 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;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user