终于A了这题
发一篇题解供人参考
同时谢谢这位dalao所述的注意事项给了我很多提醒
思路都在注释里了
#include <iostream>
#include <cstdio>
using namespace std;
const int N = 15, M = 2010;
struct pig
{
int hp, size; //生命,手牌数
char id; //身份
char cards[M]; //手牌
bool zhuge; //有没有武器
}a[N];
int Pre[N], Next[N]; //每只猪的前一个和后一个
int n, m;
int fp_sum; //反猪数量
char mp_look[N], card_stack[M], str[N]; //在主猪看来每只猪的身份,也是每只猪已经跳的身份, 卡牌堆, 输入用的临时字符串
bool end_game; //游戏是否结束
/*
void Debug() //调试用
{
puts("");
for (int i = 1; i <= n; i++)
{
printf("a[%d].hp=%d\n", i, a[i].hp);
printf("a[%d].size=%d\n", i, a[i].size);
printf("a[%d].Pre=%d\n", i, Pre[i]);
printf("a[%d].Next=%d\n", i, Next[i]);
printf("a[%d].id=%c\n", i, a[i].id);
printf("a[%d].zhuge=%d\n", i, a[i].zhuge);
printf("a[%d].cards[]: ", i);for (int j = 1; j <= a[i].size; j++) printf("%c ", a[i].cards[j]);puts("");
}
puts("");
}
*/
void get_card(int x)
{
//没牌时重复抓最后一张
if (m == 0) m++;
a[x].cards[++a[x].size] = card_stack[m--];
}
void KO(int x, int y)
{
//是否有桃,有就用
for (int i = 1; i <= a[y].size; i++)
if (a[y].cards[i] == 'P')
{
a[y].cards[i] = '#';
a[y].hp++;
return ;
}
//判断是否结束
if (a[y].id == 'F') fp_sum--;
if (y == 1 || fp_sum == 0)
{
end_game = true;
return ;
}
//改变攻击距离
Pre[Next[y]] = Pre[y];
Next[Pre[y]] = Next[y];
//杀反贼,摸三张
if (a[y].id == 'F')
{
get_card(x);
get_card(x);
get_card(x);
}
//主杀忠,弃全部牌
if (x == 1 && a[y].id == 'Z')
{
a[x].size = 0;
a[x].zhuge = false;
}
}
void Kill(int x, int y)
{
//是否有闪
for (int i = 1; i <= a[y].size; i++)
if (a[y].cards[i] == 'D')
{
a[y].cards[i] = '#';
return ;
}
//没闪,减血
a[y].hp--;
if (a[y].hp <= 0) KO(x, y);
}
bool wxkj(int x, int y, bool z)
{
//z表示是否是递归的
int i = x;
while (1)
{
if (z)
{
//无条件帮队友
if (mp_look[y] == a[i].id || (mp_look[y] == 'M' && a[i].id == 'Z') || (mp_look[y] == 'Z' && a[i].id == 'M'))
for (int j = 1; j <= a[i].size; j++)
if (a[i].cards[j] == 'J')
{
a[i].cards[j] = '#';
mp_look[i] = a[i].id; //跳身份
return !wxkj(i, x, 0);
}
}
else
{
//无条件无懈敌对
if ((mp_look[x] == 'F' && (a[i].id == 'M' || a[i].id == 'Z')) || (a[i].id == 'F' && (mp_look[x] == 'M' || mp_look[x] == 'Z')))
for (int j = 1; j <= a[i].size; j++)
if (a[i].cards[j] == 'J')
{
a[i].cards[j] = '#';
mp_look[i] = a[i].id; //跳身份
return !wxkj(i, x, 0);
}
}
i = Next[i]; //下一个
if (i == x) break; //如果转一圈了,break
}
return false;
}
void aoe(int x, char ch)
{
//群伤,ch表示每个角色要依次出杀还是依次出闪
for (int i = Next[x]; i != x; i = Next[i])
{
if (!wxkj(x, i, true)) //不能被无懈
{
int j;
for (j = 1; j <= a[i].size; j++)
if (a[i].cards[j] == ch) //查看有没有,有就出
{
a[i].cards[j] = '#';
break;
}
if (j > a[i].size) //没有,减血
{
a[i].hp--;
if (i == 1 && mp_look[x] == '#') mp_look[x] = 'L';
if (a[i].hp == 0) KO(x, i);
if (end_game) return ;
}
}
}
}
void duel(int x, int y)
{
//决斗
int i = 1, j = 1;
if (wxkj(x, y, true)) return ; //能被无懈,return
if (x == 1 && a[y].id == 'Z') //忠猪不对主猪决斗
{
a[y].hp--;
if (a[y].hp == 0) KO(x, y);
return ;
}
while (1) //依次出杀,有就一定出
{
while (a[y].cards[i] != 'K' && i <= a[y].size) i++;
if (i > a[y].size)
{
a[y].hp--;
if (a[y].hp == 0) KO(x, y);
return ;
}
else a[y].cards[i] = '#';
while (a[x].cards[j] != 'K' && j <= a[x].size) j++;
if (j > a[x].size)
{
a[x].hp--;
if (a[x].hp == 0) KO(y, x);
return ;
}
else a[x].cards[j] = '#';
}
}
void init()
{
scanf("%d%d", &n, &m);
//初始化每头猪的前一只和后一只
Pre[1] = n, Next[1] = 2;
Pre[n] = n - 1, Next[n] = 1;
for (int i = 2; i < n; i++)
{
Pre[i] = i - 1;
Next[i] = i + 1;
}
//初始化主猪对每只猪的看法
mp_look[1] = 'M';
for (int i = 2; i <= n; i++) mp_look[i] = '#';
//输入每只猪的信息
for (int i = 1; i <= n; i++)
{
for (int j = 1; j < M; j++) a[i].cards[j] = '#';
scanf("%s", str);
a[i].id = str[0];
for (int j = 1; j <= 4; j++)
{
scanf("%s", str);
a[i].cards[j] = str[0];
}
a[i].hp = a[i].size = 4;
if (a[i].id == 'F') fp_sum++;
a[i].zhuge = false;
}
//输入排队,逆序存
for (int i = 1; i <= m; i++)
{
scanf("%s", str);
card_stack[m - i + 1] = str[0];
}
}
void work()
{
//有没有反猪,没有直接return
end_game = fp_sum ? false : true;
if (end_game) return ;
for (int i = 1; i; i = Next[i]) //依次摸牌
{
get_card(i);
get_card(i);
bool flag = false; //有没有用过杀
for (int j = 1; j <= a[i].size; j++)
{
if (a[i].cards[j] != '#')
{
if (a[i].hp <= 0) break; //死了,break
if (a[i].cards[j] == 'P') //是否吃桃
{
if (a[i].hp < 4)
{
a[i].cards[j] = '#';
a[i].hp++;
}
continue;
}
if (a[i].cards[j] == 'K') //杀
{
if (flag && !a[i].zhuge) continue; //用过杀了且没有猪哥连弩
if (a[i].id == 'M' && mp_look[Next[i]] != 'F' && mp_look[Next[i]] != 'L') continue; //主猪不杀反猪和类反猪以外的猪
if (a[i].id == 'Z' && mp_look[Next[i]] != 'F') continue; //忠猪不杀反猪以外的猪
if (a[i].id == 'F' && mp_look[Next[i]] != 'M' && mp_look[Next[i]] != 'Z') continue; //反猪不杀主猪和忠猪以外的猪
a[i].cards[j] = '#'; //否则就杀
Kill(i, Next[i]);
mp_look[i] = a[i].id; //跳身份
flag = true; //用过了
if (end_game) return ;
continue;
}
if (a[i].cards[j] == 'F')
{
if (a[i].id == 'F')
{
a[i].cards[j] = '#'; //是反猪就直接对主猪用
duel(i, 1);
mp_look[i] = a[i].id;
if (end_game) return ;
j = 0; //可能掉血,须从新扫一遍,看有没有桃
continue;
}
for (int k = Next[i]; k != i; k = Next[k]) //找对谁使用
{
if ((a[i].id == 'M' && (mp_look[k] == 'F' || mp_look[k] == 'L')) || (a[i].id == 'Z' && mp_look[k] == 'F'))
{
a[i].cards[j] = '#';
duel(i, k);
mp_look[i] = a[i].id; //跳身份
if (end_game) return ;
j = 0; //可能掉血,须从新扫一遍,看有没有桃
break;
}
}
continue;
}
if (a[i].cards[j] == 'N' || a[i].cards[j] == 'W') //群体伤害,直接用
{
if (a[i].cards[j] == 'N') aoe(i, 'K'); //每只猪出杀
else aoe(i, 'D'); //每只猪出闪
a[i].cards[j] = '#';
if (end_game) return ;
j = 0; ////可能掉血,须从新扫一遍,看有没有桃
continue;
}
if (a[i].cards[j] == 'Z') //猪哥连弩,直接装
{
a[i].cards[j] = '#';
a[i].zhuge = true;
j = 0; //从新扫一边看又没有杀
continue;
}
}
}
}
}
void print()
{
//看是主猪赢还是反猪赢
if (fp_sum <= 0) puts("MP");
else puts("FP");
//输出每只猪的状态
for (int i = 1; i <= n; i++)
{
if (a[i].hp <= 0)
{
puts("DEAD");
continue;
}
for (int j = 1; j <= a[i].size; j++) if (a[i].cards[j] != '#') printf("%c ", a[i].cards[j]);
puts("");
}
}
int main()
{
init();
work();
print();
return 0;
}