[SDOI2010]猪国杀
题目描述
游戏背景
《猪国杀》是一种多猪牌类回合制游戏,一共有
3
3
3
种角色:主猪,忠猪,反猪。每局游戏主猪有且只有
1
1
1
只,忠猪和反猪可以有多只,每只猪扮演
1
1
1
种角色。
游戏目的
主猪 /
MP
\texttt{MP}
MP
:自己存活的情况下消灭所有的反猪。
忠猪 /
ZP
\texttt{ZP}
ZP
:不惜一切保护主猪,胜利条件与主猪相同。
反猪 /
FP
\texttt{FP}
FP
:杀死主猪。
游戏过程
游戏开始时,每个玩家手里都会有
4
4
4
张牌,且体力上限和初始体力都是
4
4
4
。
开始游戏时,从主猪开始,按照逆时针方向(数据中就是按照编号从
1
,
2
,
3
…
n
,
1
…
1 , 2, 3 \ldots n , 1 \ldots
1
,
2
,
3
…
n
,
1
…
的顺序)依次行动。
每个玩家自己的回合可以分为 2 个阶段:
-
摸牌阶段
:从牌堆顶部摸
22
2
张牌,依次放到手牌的最右边; -
出牌阶段
:你可以使用任意张牌,每次使用牌的时候都使用最靠左的能够使用的牌。当然,要满足如下规则:-
如果没有猪哥连弩,每个出牌阶段只能使用
11
1
次「杀」来攻击; - 任何牌被使用后被弃置(武器是装备上);被弃置的牌以后都不能再用,即与游戏无关。
-
如果没有猪哥连弩,每个出牌阶段只能使用
各种牌介绍
每张手牌用
1
1
1
个字母表示,字母代表牌的种类。
基本牌
-
『桃 /
P\texttt{P}
P
』在自己的回合内,如果自己的体力值不等于体力上限,那么使用
11
1
个桃可以为自己补充
11
1
点体力,否则不能使用桃;桃只能对自己使用;在自己的回合外,如果自己的血变为
00
0
或者更低,那么也可以使用。 -
『杀 /
K\texttt{K}
K
』在自己的回合内,对攻击范围内除自己以外的
11
1
名角色使用。如果没有被『闪』抵消,则造成
11
1
点伤害。无论有无武器,杀的攻击范围都是
11
1
。 -
『闪 /
D\texttt{D}
D
』当你受到杀的攻击时,可以弃置
11
1
张闪来抵消杀的效果。
锦囊牌
-
『决斗 /
F\texttt{F}
F
』出牌阶段,对除自己以外任意
11
1
名角色使用,由目标角色先开始,自己和目标角色轮流弃置
11
1
张杀,首先没有杀可弃的一方受到
11
1
点伤害,另一方视为此伤害的来源。 -
『南猪入侵 /
N\texttt{N}
N
』出牌阶段,对除你以外所有角色使用,按逆时针顺序从使用者下家开始依次结算,除非弃置
11
1
张杀,否则受到
11
1
点伤害。 -
『万箭齐发 /
W\texttt{W}
W
』和南猪入侵类似,不过要弃置的不是杀而是闪。 -
『无懈可击 /
J\texttt{J}
J
』在目标锦囊生效前抵消其效果。每次有
11
1
张锦囊即将生效时,从使用这张锦囊的猪开始,按照逆时针顺序,依次得到使用无懈可击的机会;效果:用于决斗时,决斗无效并弃置;用于南猪入侵或万箭齐发时,当结算到某个角色时才能使用,当前角色不需弃置牌并且不会受到伤害(仅对
11
1
个角色产生效果);用于无懈可击时,成为目标的无懈可击被无效。
装备牌
-
『猪哥连弩 /
Z\texttt{Z}
Z
』武器,攻击范围
11
1
,出牌阶段你可以使用任意张杀; 同一时刻最多只能装
11
1
把武器;如果先前已经有了
11
1
把武器,那么之后再装武器的话,会弃置以前的武器来装现在的武器。
特殊事件及概念解释
-
伤害来源
:杀、南猪入侵、万箭齐发的伤害来源均是使用该牌的猪,决斗的伤害来源如上; -
距离
:两只猪的距离定义为沿着逆时针方向间隔的猪数
+1
+1
+
1
。即初始时
11
1
和
22
2
的距离为
11
1
,但是
22
2
和
11
1
的距离就是
n−
1
n-1
n
−
1
。注意一个角色的死亡会导致一些猪距离的改变; -
玩家死亡
:如果该玩家的体力降到
00
0
或者更低,并且自己手中没有足够的桃使得自己的体力值回到
11
1
,那么就死亡了,死亡后所有的牌(装备区,手牌区)被弃置; -
奖励与惩罚
:反猪死亡时,最后一个伤害来源处(即使是反猪)立即摸
33
3
张牌。忠猪死亡时,如果最后一个伤害来源是主猪,那么主猪所有装备牌、手牌被弃置。
注意:一旦达成胜利条件,游戏立刻结束,因此即使会摸
3
3
3
张牌或者还有牌可以用也不用执行了。
现在,我们已经知道每只猪的角色、手牌,还有牌堆初始情况,并且假设每个角色会按照如下的行为准则进行游戏,你需要做的就是告诉小猪 iPig 最后的结果。
几种行为
-
献殷勤
:使用无懈可击挡下南猪入侵、万箭齐发、决斗;使用无懈可击抵消表敌意; -
表敌意
:对某个角色使用杀、决斗;使用无懈可击抵消献殷勤; -
跳忠
:即通过行动表示自己是忠猪。跳忠行动就是对主猪或对某只已经跳忠的猪献殷勤,或者对某只已经跳反的猪表敌意; -
跳反
:即通过行动表示自己是反猪。跳反行动就是对主猪或对某只已经跳忠的猪表敌意,或者对某只已经跳反的猪献殷勤。
注意:忠猪不会跳反,反猪也不会跳忠;不管是忠猪还是反猪,能够跳必然跳
。
行动准则
共性
- 每个角色如果手里有桃且生命值未满,那么必然吃掉;
- 有南猪入侵、万箭齐发、必然使用;有装备必然装上;
- 受到杀时,有闪必然弃置;
- 响应南猪入侵或者万箭齐发时候,有杀 / 闪必然弃置;
-
不会对未表明身份的猪献殷勤(
包括自己
)。
特性
-
主猪:
-
主猪会认为「没有跳身份,且用南猪入侵 / 万箭齐发对自己造成伤害的猪」是
类
反猪(没伤害到不算,注意类反猪并没有表明身份),如果之后跳了,那么主猪会重新认识这只猪; - 对于每种表敌意的方式,对逆时针方向能够执行到的第一只类反猪或者已跳反猪表;如果没有,那么就不表敌意;
- 决斗时会不遗余力弃置杀;
- 如果能对已经跳忠的猪或自己献殷勤,那么一定献;如果能够对已经跳反的猪表敌意,那么一定表。
-
主猪会认为「没有跳身份,且用南猪入侵 / 万箭齐发对自己造成伤害的猪」是
-
忠猪:
- 对于每种表敌意的方式,对「逆时针方向能够执行到的第一只已经跳反的猪」表,如果没有,那么就不表敌意;
- 决斗时,如果对方是主猪,那么不会弃置杀,否则,会不遗余力弃置杀;
- 如果有机会对主猪或者已经跳忠的猪献殷勤,那么一定献。
-
反猪:
- 对于每种表敌意的方式,如果有机会则对主猪表,否则,对「逆时针方向能够执行到的第一只已经跳忠的猪」表,如果没有,那么就不表敌意;
- 决斗时会不遗余力弃置杀;
- 如果有机会对已经跳反的猪献殷勤,那么一定献。
限于 iPig 只会用 P++ 语言写 A + B,他请你用 Pigcal (Pascal)、P © 或 P++ (C++) 语言来帮他预测最后的结果。
输入格式
输入文件第一行包含两个正整数 $ n $ $ (2 \leqslant n \leqslant 10) $ 和
m
m
m
$ (m \leqslant 2000) $,分别代表玩家数和牌堆中牌的数量。数据保证牌的数量够用。
接下来
n
n
n
行,每行
5
5
5
个字符串,依次表示对第
i
i
i
只猪的角色和初始 $4 $ 张手牌描述。编号为
1
1
1
的肯定是主猪。
再接下来一行,一共
m
m
m
个字符串,按照从牌堆顶部到牌堆底部的顺序描述每张牌。
注意:所有的相邻的两个字符串都严格用
1
1
1
个空格隔开,行尾没有多余空格
。
输出格式
输出数据第一行包含一个字符串代表游戏结果。如果是主猪胜利,那么输出
MP
\texttt{MP}
MP
,否则输出
FP
\texttt{FP}
FP
。数据保证游戏总会结束。
接下来
n
n
n
行,第
i
i
i
行是对第
i
i
i
只猪的手牌描述(注意只需要输出手牌),按照手牌从左往右的顺序输出,相邻两张牌用
1
1
1
个空格隔开,行末尾没有多余空格。如果这只猪已阵亡,那么只要输出
DEAD
\texttt{DEAD}
DEAD
即可。
注意:如果要输出手牌而没有手牌的话,那么只需输出
1
1
1
个空行
。
由于数据问题,若牌堆已空,按照每次抽牌抽到的都是最后一张。
样例 #1
样例输入 #1
3 10
MP D D F F
ZP N N N D
FP J J J J
F F D D J J F F K D
样例输出 #1
FP
DEAD
DEAD
J J J J J J D
提示
样例解释
第一回合:
- 主猪没有目标可以表敌意;
-
接下来忠猪使用了
33
3
张南猪入侵,主猪掉了
33
3
点体力,并认为该角色为类反猪,
33
3
号角色尽管手里有无懈可击,但是因为自己未表明身份,所以同样不能对自己用,乖乖掉
33
3
点体力;
下一回合:
- 反猪无牌可出;
-
接下来主猪对着类反猪爆发,使用
44
4
张决斗,忠猪死亡,结果主猪弃掉所有牌; -
下来反猪摸到
11
1
张杀直接杀死主猪获胜。
子任务
一共
20
20
2
0
组测试数据,每个点
5
5
5
分。
10
%
10\%
1
0
%
的数据没有锦囊牌,另外
20
%
20\%
2
0
%
的数据没有无懈可击。
题解
大大大大大大大大大大模拟!!!!!!
这题非常简单,只需模拟一遍即可
我也就WA了十几遍
先将用结构体玩家信息储存起来
struct Player{
int s,nxt,lst; //体力,上一名与下一名玩家
string id; //MP主猪,ZP忠猪,FP反猪
int cl; //手牌数
char c[MAXCARD]; //P桃,K杀,D闪,F决斗,N南猪入侵,W万箭齐发,J无懈可击
bool f; //1表示装备诸哥连弩,0反之
bool dead; //0表示活着,1死亡
}player[MAXPLAYER];
摸牌
int m,cl = 1; //牌堆中牌数,现在摸到的牌数
char card[MAXCARD];
void mp(int x){ //摸牌
if(cl > m)
player[x].c[++player[x].cl] = card[m]; //2000张牌居然不够用
else
player[x].c[++player[x].cl] = card[cl];
cl++;
}
输入与初始化
cin >> n >> m;
for(int i=1;i<=n;i++){
cin >> player[i].id;
for(int j=1;j<=4;j++) cin >> player[i].c[j];
if(player[i].id == "FP") fz++;
player[i].s = player[i].cl = 4;
player[i].f = false;
player[i].dead = false;
player[i].nxt = i+1; player[i].lst = i-1;
}
player[1].lst = n; player[n].nxt = 1;
for(int i=1;i<=m;i++) cin >> card[i];
sf[1] = "MP"; for(int i=2;i<=n;i++) sf[i] = "U";//在主猪眼中身份,U = unknown
输出
if(player[1].dead) cout << "FP\n";//主猪没了反猪赢
else cout << "MP\n";
for(int i=1;i<=n;i++){
if(player[i].dead) cout << "DEAD\n";
else{
for(int j=1;j<=player[i].cl;j++)
if(player[i].c[j] != 'U' && player[i].c[j] != ' ')
cout << player[i].c[j] << " ";
cout <<"\n";
}
}
10 pts
先做没有锦囊牌的情况
需要注意的是
没有猪哥连弩时杀只能出一次
反猪只会攻击主猪与忠猪
主猪只会攻击反猪和类反猪
忠猪只会攻击反猪
攻击后(即表敌意)会暴露身份
主程序
bool ed;//表示游戏是否已经结束
void slove(){
char nc;//now_card
ed = (fz == 0);//一局游戏没有反贼直接游戏结束
if(ed) return;
for(int i=1;i;i=player[i].nxt){
mp(i); mp(i);//每人先摸两张牌
bool k = true; //判断是否能使用过杀
for(int j=1;j<=player[i].cl;j++){
nc = player[i].c[j];
if(nc == 'U') continue;
if(player[i].dead) break;
if(nc == 'P'){//血不满可以直接回血
if(player[i].s != 4) player[i].s++,player[i].c[j] = 'U';
continue;
}
else if(nc == 'K'){
if(!k && !player[i].f) continue;//使用过杀且没猪哥连弩
if(player[i].id == "MP" && sf[player[i].nxt] != "FP" && sf[player[i].nxt] != "LFP") continue;//主猪只会攻击反猪和类反猪
if(player[i].id == "ZP" && sf[player[i].nxt] != "FP") continue;//忠猪只会攻击反猪
if(player[i].id == "FP" && sf[player[i].nxt] != "MP" && sf[player[i].nxt] != "ZP") continue;//反猪只会攻击主猪与忠猪
player[i].c[j] = 'U';
kil(i,player[i].nxt);
sf[i] = player[i].id;
k = false;
if(ed) return;
continue;
}
else if(nc == 'Z'){///装备猪哥连弩
player[i].f = true;
player[i].c[j] = 'U';
j = 0;//因为前面可能有杀可以用,所以要重头找一遍
continue;
}
)
}
}
杀
void kil(int x,int y){ //杀
for(int i=1;i<=player[y].cl;i++)
if(player[y].c[i] == 'D'){//如果有闪就闪
player[y].c[i] = 'U';
return;
}
player[y].s--;
if(!player[y].s) js(x,y);//记得判断是否有人死亡
}
判断击杀
void js(int x,int y){ //判断击杀
for(int i=1;i<=player[y].cl;i++)
if(player[y].c[i] == 'P'){//有桃就回血
player[y].c[i] = 'U';
player[y].s++;
return;
}
player[y].dead = 1;//没有桃就无了
player[player[y].lst].nxt = player[y].nxt;//一个玩家死亡会改变其他玩家位置
player[player[y].nxt].lst = player[y].lst;
if(y == 1){ed = true; return;}//主猪没了,反猪胜利
if(player[y].id == "FP") fz--;
if(!fz){ed = true;return;}//反猪没了,主猪胜利
if(player[y].id == "FP"){mp(x);mp(x);mp(x);}//杀死反猪摸三张牌
if(player[x].id == "MP" && player[y].id == "ZP") player[x].cl = 0,player[x].f = false;
//主猪杀死忠猪弃牌,装备
}
和在一起即可
30 pts
先不管无懈可击,做其他锦囊牌
记住每次进行伤害攻击后都要判断是否游戏结束
注意南猪入侵和万箭齐发使用后不会暴露身份
主程序
bool ed;//表示游戏是否已经结束
void slove(){
char nc;//now_card
ed = (fz == 0);//一局游戏没有反贼直接游戏结束
if(ed) return;
for(int i=1;i;i=player[i].nxt){
mp(i); mp(i);//每人先摸两张牌
bool k = true; //判断是否能使用过杀
for(int j=1;j<=player[i].cl;j++){
nc = player[i].c[j];
if(nc == 'U') continue;
if(player[i].dead) break;
if(nc == 'P'){//血不满可以直接回血
if(player[i].s != 4) player[i].s++,player[i].c[j] = 'U';
continue;
}
else if(nc == 'K'){
if(!k && !player[i].f) continue;//使用过杀且没猪哥连弩
if(player[i].id == "MP" && sf[player[i].nxt] != "FP" && sf[player[i].nxt] != "LFP") continue;//主猪只会攻击反猪和类反猪
if(player[i].id == "ZP" && sf[player[i].nxt] != "FP") continue;//忠猪只会攻击反猪
if(player[i].id == "FP" && sf[player[i].nxt] != "MP" && sf[player[i].nxt] != "ZP") continue;//反猪只会攻击主猪与忠猪
player[i].c[j] = 'U';
kil(i,player[i].nxt);
sf[i] = player[i].id;
k = false;
if(ed) return;
continue;
}
else if(nc == 'Z'){///装备猪哥连弩
player[i].f = true;
player[i].c[j] = 'U';
j = 0;//因为前面可能有杀可以用,所以要重头找一遍,下同
continue;
}
else if(nc == 'W'){//万箭齐发
wjqf(i);
player[i].c[j] = 'U';
if(ed) return;
j=0;
continue;
}
else if(nc == 'N'){
nzrq(i);
player[i].c[j] = 'U';
if(ed) return;
j=0;
continue;
}
else if(nc == 'F'){
if(player[i].id == "FP"){
player[i].c[j] = 'U';
jd(i,1);//反猪必回对主猪表敌意
sf[i] = player[i].id;
if(ed) return;
j=0;
continue;
}
for(int k=player[i].nxt;k!=i;k=player[k].nxt){
if(player[i].id == "MP" && (sf[k] == "FP" || sf[k] == "LFP") || player[i].id == "ZP" && sf[k] == "FP"){//只会对敌人表敌意
player[i].c[j] = 'U';
jd(i,k);
sf[i] = player[i].id;//表敌意后身份暴露
if(ed) return;
j=0;
break;
}
}
continue;
}
)
}
}
南猪入侵
依题模拟
void nzrq(int x){ //南猪入侵
for(int i=player[x].nxt;i!=x;i=player[i].nxt){
int j;
for(j=1;j<=player[i].cl;j++){
if(player[i].c[j] == 'K'){
player[i].c[j] = 'U';
break;
}
}
if(j > player[i].cl){
player[i].s--;
if(!player[i].s) js(x,i);
if(i == 1 && sf[x] == "U") sf[x] = "LFP";
if(ed) return;
}
}
}
万箭齐发
跟南猪入侵几乎一样,只差函数名和一个字母
void wjqf(int x){ //万箭齐发
for(int i=player[x].nxt;i!=x;i=player[i].nxt){
int j;
for(j=1;j<=player[i].cl;j++){
if(player[i].c[j] == 'D'){
player[i].c[j] = 'U';
break;
}
}
if(j > player[i].cl){
player[i].s--;
if(i == 1 && sf[x] == "U") sf[x] = "LFP";
if(!player[i].s) js(x,i);
if(ed) return;
}
}
}
决斗
void jd(int x,int y){ //决斗
if(wxkj(x,y,1)) return;
if(x == 1 && player[y].id == "ZP"){
//注意忠猪被主猪打只会乖乖掉血
player[y].s--;
if(!player[y].s) js(x,y);
return;
}
int j,k;
j = k = 1;
while(true){
for(;j<=player[y].cl;j++)//注意是对面先而不是自己
if(player[y].c[j] == 'K') break;
if(j > player[y].cl){
player[y].s--;
if(!player[y].s) js(x,y);
return;
}
else player[y].c[j] = 'U';
for(;k<=player[x].cl;k++)
if(player[x].c[k] == 'K') break;
if(k > player[x].cl){
player[x].s--;
if(!player[x].s) js(y,x);//不要写反
return;
}
else player[x].c[k] = 'U';
}
}
100 pts
接下来就是最难的无懈可击
分两种情况讨论
第一种无懈可击用来抵消无懈可击
第二种则反之
可以用类似于
d
f
s
dfs
d
f
s
实现
无懈可击
bool wxkj(int x,int y,bool z){ //无懈可击 z:0表示抵无懈可击
int i = x;
while(true){
if(z){
if(player[i].id == sf[y] || (player[i].id == "MP" && sf[y] == "ZP") || (player[i].id == "ZP" && sf[y] == "MP"))//为队友抵
for(int j=1;j<=player[i].cl;j++)
if(player[i].c[j] == 'J'){
player[i].c[j] = 'U';
sf[i] = player[i].id;
return !wxkj(i,x,0);
}
}
else{
if((sf[x] == "FP" && (player[i].id == "MP" || player[i].id == "ZP")) || (player[i].id == "FP" && (sf[x] == "MP" || sf[x] == "ZP")))//去除敌人的无懈可击
for(int j=1;j<=player[i].cl;j++)
if(player[i].c[j] == 'J'){
player[i].c[j] = 'U';
sf[i] = player[i].id;
return !wxkj(i,x,0);
}
}
i = player[i].nxt;
if(i == x) break;
}
return false;
}
完整代码
#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
using namespace std;
const int MAXPLAYER = 15;
const int MAXCARD = 2100;
int n; //玩家数
struct Player{
int s,nxt,lst; //体力
string id; //MP主猪,ZP忠猪,FP反猪
int cl; //手牌数
char c[MAXCARD]; //P桃,K杀,D闪,F决斗,N南猪入侵,W万箭齐发,J无懈可击
bool f; //1表示装备诸哥连弩,0反之
bool dead; //0表示活着,1死亡
}player[MAXPLAYER];
bool ed = false;
int m,cl = 1; //牌堆中牌数,现在摸到的牌数
char card[MAXCARD]; //牌堆中牌
string sf[MAXPLAYER]; //主猪眼中身份
int fz; //反贼数
void mp(int x){ //摸牌
if(cl > m){
player[x].c[++player[x].cl] = card[m];
}
else{
player[x].c[++player[x].cl] = card[cl];
}
cl++;
}
void js(int x,int y){ //判断击杀
for(int i=1;i<=player[y].cl;i++)
if(player[y].c[i] == 'P'){
player[y].c[i] = 'U';
player[y].s++;
return;
}
player[y].dead = 1;
player[player[y].lst].nxt = player[y].nxt;
player[player[y].nxt].lst = player[y].lst;
if(y == 1){ed = true; return;}
if(player[y].id == "FP") fz--;
if(!fz){ed = true;return;}
if(player[y].id == "FP"){mp(x);mp(x);mp(x);}
if(player[x].id == "MP" && player[y].id == "ZP") player[x].cl = 0,player[x].f = false;
}
void kil(int x,int y){ //杀
for(int i=1;i<=player[y].cl;i++)
if(player[y].c[i] == 'D'){
player[y].c[i] = 'U';
return;
}
player[y].s--;
if(!player[y].s) js(x,y);
}
bool wxkj(int x,int y,bool z){ //无懈可击 z:0表示抵无懈可击
int i = x;
while(true){
if(z){
if(player[i].id == sf[y] || (player[i].id == "MP" && sf[y] == "ZP") || (player[i].id == "ZP" && sf[y] == "MP"))
for(int j=1;j<=player[i].cl;j++)
if(player[i].c[j] == 'J'){
player[i].c[j] = 'U';
sf[i] = player[i].id;
return !wxkj(i,x,0);
}
}
else{
if((sf[x] == "FP" && (player[i].id == "MP" || player[i].id == "ZP")) || (player[i].id == "FP" && (sf[x] == "MP" || sf[x] == "ZP")))
for(int j=1;j<=player[i].cl;j++)
if(player[i].c[j] == 'J'){
player[i].c[j] = 'U';
sf[i] = player[i].id;
return !wxkj(i,x,0);
}
}
i = player[i].nxt;
if(i == x) break;
}
return false;
}
void nzrq(int x){ //南猪入侵
for(int i=player[x].nxt;i!=x;i=player[i].nxt){
if(wxkj(x,i,1)) continue;
int j;
for(j=1;j<=player[i].cl;j++){
if(player[i].c[j] == 'K'){
player[i].c[j] = 'U';
break;
}
}
if(j > player[i].cl){
player[i].s--;
if(!player[i].s) js(x,i);
if(i == 1 && sf[x] == "U") sf[x] = "LFP";
if(ed) return;
}
}
}
void wjqf(int x){ //万箭齐发
for(int i=player[x].nxt;i!=x;i=player[i].nxt){
if(wxkj(x,i,1)) continue;
int j;
for(j=1;j<=player[i].cl;j++){
if(player[i].c[j] == 'D'){
player[i].c[j] = 'U';
break;
}
}
if(j > player[i].cl){
player[i].s--;
if(i == 1 && sf[x] == "U") sf[x] = "LFP";
if(!player[i].s) js(x,i);
if(ed) return;
}
}
}
void jd(int x,int y){ //决斗
if(wxkj(x,y,1)) return;
if(x == 1 && player[y].id == "ZP"){
player[y].s--;
if(!player[y].s) js(x,y);
return;
}
int j,k;
j = k = 1;
while(true){
for(;j<=player[y].cl;j++)
if(player[y].c[j] == 'K')
break;
if(j > player[y].cl){
player[y].s--;
if(!player[y].s) js(x,y);
return;
}
else player[y].c[j] = 'U';
for(;k<=player[x].cl;k++)
if(player[x].c[k] == 'K')
break;
if(k > player[x].cl){
player[x].s--;
if(!player[x].s) js(y,x);
return;
}
else player[x].c[k] = 'U';
}
}
void slove(){
char nc;
ed = (fz == 0);
if(ed) return;
for(int i=1;i;i=player[i].nxt){
mp(i); mp(i);
bool k = true; //判断是否能使用过杀
for(int j=1;j<=player[i].cl;j++){
nc = player[i].c[j];
if(nc == 'U') continue;
if(player[i].dead) break;
if(nc == 'P'){
if(player[i].s != 4) player[i].s++,player[i].c[j] = 'U';
continue;
}
else if(nc == 'K'){
if(!k && !player[i].f) continue;
if(player[i].id == "MP" && sf[player[i].nxt] != "FP" && sf[player[i].nxt] != "LFP") continue;
if(player[i].id == "ZP" && sf[player[i].nxt] != "FP") continue;
if(player[i].id == "FP" && sf[player[i].nxt] != "MP" && sf[player[i].nxt] != "ZP") continue;
player[i].c[j] = 'U';
kil(i,player[i].nxt);
sf[i] = player[i].id;
k = false;
if(ed) return;
continue;
}
else if(nc == 'Z'){
player[i].f = true;
player[i].c[j] = 'U';
j = 0;
continue;
}
else if(nc == 'W'){
wjqf(i);
player[i].c[j] = 'U';
if(ed) return;
j=0;
continue;
}
else if(nc == 'N'){
nzrq(i);
player[i].c[j] = 'U';
if(ed) return;
j=0;
continue;
}
else if(nc == 'F'){
if(player[i].id == "FP"){
player[i].c[j] = 'U';
jd(i,1);
sf[i] = player[i].id;
if(ed) return;
j=0;
continue;
}
for(int k=player[i].nxt;k!=i;k=player[k].nxt){
if(player[i].id == "MP" && (sf[k] == "FP" || sf[k] == "LFP") || player[i].id == "ZP" && sf[k] == "FP"){
player[i].c[j] = 'U';
jd(i,k);
sf[i] = player[i].id;
if(ed) return;
j=0;
break;
}
}
continue;
}
}
}
}
int main(){
ios::sync_with_stdio(false);
cin >> n >> m;
for(int i=1;i<=n;i++){
cin >> player[i].id;
for(int j=1;j<=4;j++) cin >> player[i].c[j];
if(player[i].id == "FP") fz++;
player[i].s = player[i].cl = 4;
player[i].f = false;
player[i].dead = false;
player[i].nxt = i+1; player[i].lst = i-1;
}
player[1].lst = n; player[n].nxt = 1;
for(int i=1;i<=m;i++) cin >> card[i];
sf[1] = "MP"; for(int i=2;i<=n;i++) sf[i] = "U";
slove();
if(player[1].dead) cout << "FP\n";
else cout << "MP\n";
for(int i=1;i<=n;i++){
if(player[i].dead) cout << "DEAD\n";
else{
for(int j=1;j<=player[i].cl;j++)
if(player[i].c[j] != 'U' && player[i].c[j] != ' ')
cout << player[i].c[j] << " ";
cout <<"\n";
}
}
return 0;
}
然后