最近题荒,不知道做什么题,就心血来潮挖了一个大坑
一堆猪玩《猪国杀》,想想就\(interesting\)
最终万分艰难的\(A\)掉了, 留贴纪念
坑点
这道题,嗯……,可以说,全是坑点……
- 如果牌堆没牌了,那么会一直摸最后一张牌
- 距离的意思其实是:每只猪只能杀到他逆时针方向的第一只存活的猪
- 主猪杀死忠臣后一定要把牌弃的的干干净净,不要忘了诸葛连弩
- 出无懈可击和杀以及决斗都会暴露身份
- 反猪只会和主猪决斗
- 无懈可击一定要注意,只会给跳身份的人用
- 主公默认已跳身份
其他的还有一堆的坑点,写的时候一定要注意
调试方法
可以做一个解说器,输出游戏过程,然后下载\(LOJ\)上的数据,与\(AC\)代码比较输出的过程,效果十分不错
解说器示例:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#define LL long long
using namespace std;
LL read() {
LL k = 0, f = 1; char c = getchar();
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9')
k = k * 10 + c - 48, c = getchar();
return k * f;
}
char read_c() {
char c = getchar();
while ((c < 'a' || c > 'b') && (c < 'A' || c > 'Z')) c = getchar();
while ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) return c;
return c;
}
int n, m;
struct zzz {
int tot, hp, dis, id; // 手牌数量 血量 距离 身份:1=mp 2=zp 3=fp
bool lfz, zgln, wszd, dead, one; // 类反猪标志 诸葛连弩 表明身份 死亡 杀只能用一次
char cord[2010]; // 手牌
}pig[110];
char allc[2010]; int pos;
int fp_num;
void mopai(int num, int k) {
int &tot = pig[num].tot;
for(int i = 1; i <= k; ++i) {
if(pos == m) --pos;
pig[num].cord[++tot] = allc[++pos];
}
}
bool waf(int x, int y) { // 判断x是否会对y献殷勤
zzz &px = pig[x], &py = pig[y];
if(py.wszd && (px.id == py.id || (px.id == 2 && py.id == 1) || (px.id == 1 && py.id == 2))) return 1;
return 0;
}
bool godie(int x, int y){ // 判断x是否会对y表敌意
zzz &px = pig[x], &py = pig[y];
if(py.wszd && (px.id == 2 || px.id == 1) && py.id == 3) return 1;
if(py.wszd && px.id == 3 && (py.id == 1 || py.id == 2)) return 1;
if(py.lfz && px.id == 1) return 1;
return 0;
}
bool wxkj(int num, int k, int lx) {
for(int i = num, ii = 1; ii <= n; i = i%n+1, ++ii) {
if(!lx && waf(i, k)) {
for(int j = 1; j <= pig[i].tot; ++j) {
if(pig[i].cord[j] == 'J') {
printf("玩家%d使用了无懈可击\n" ,i);
pig[i].wszd = 1, pig[i].cord[j] = '*', pig[i].lfz = 0;
//if(pig[2].wszd) printf("2号猪暴露身份\n\n");
int cnt = i%n+1;
if(wxkj(cnt, k, lx^1)) return 0; else return 1;
}
}
}
if(lx && godie(i, k)) {
for(int j = 1; j <= pig[i].tot; ++j) {
if(pig[i].cord[j] == 'J') {
printf("玩家%d使用了无懈可击\n" ,i);
pig[i].wszd = 1, pig[i].cord[j] = '*', pig[i].lfz = 0;
int cnt = i%n+1;
if(wxkj(cnt, k, lx^1)) return 0; else return 1;
}
}
}
}
return 0;
}
void gameover(int flag) {
printf("游戏结束\n");
if(flag == 1) puts("MP");
else puts("FP");
for(int i = 1; i <= n; ++i) {
if(pig[i].dead) {
puts("DEAD"); continue;
}
for(int j = 1; j <= pig[i].tot; ++j) {
if(pig[i].cord[j] != '*') printf("%c ", pig[i].cord[j]);
}
printf("\n");
}
exit(0);
}
void die(int num, int vic) { // num 伤害来源, vic 濒死
zzz &p = pig[vic];
for(int i = 1; i <= p.tot; ++i) {
if(p.cord[i] == 'P') {
printf("玩家%d对自己使用了桃,回复了一滴血\n", vic);
p.cord[i] = '*', ++p.hp; return ;
}
}
printf("玩家%d死亡,击杀者为玩家%d\n", vic, num);
p.dead = 1;
for(int i = 1; i <= p.tot; ++i) p.cord[i] = '*';
if(p.id == 1) gameover(2); // 反猪胜利
if(p.id == 3) {
--fp_num; if(!fp_num) gameover(1); //主猪胜利
mopai(num, 3);
printf("玩家%d杀死了反贼,抽三张牌\n",num);
}
if(p.id == 2 && pig[num].id == 1) {
for(int i = 1; i <= pig[num].tot; ++i)
pig[num].cord[i] = '*';
pig[num].zgln = 0;
printf("主公杀死了忠臣,弃掉所有手牌\n");
}
int ff = 0, fff = 0;
for(int i = n; i >= 1; --i) {
if(!pig[i].dead) pig[i].dis = ff;
if(!fff && !pig[i].dead) fff = i;
ff = i;
}
pig[fff].dis = 1;
}
bool jd(int x, int y) {
zzz &px = pig[x], &py = pig[y];
int xx = 0, yy = 0;
for(int i = 1; i <= px.tot; ++i)
if(px.cord[i] == 'K') ++xx;
for(int i = 1; i <= py.tot; ++i)
if(py.cord[i] == 'K') ++yy;
if(xx >= yy) {
for(int i = 1, num = 1; num <= yy; ++i)
if(px.cord[i] == 'K') px.cord[i] ='*', ++num;
for(int i = 1, num = 1; num <= yy; ++i)
if(py.cord[i] == 'K') py.cord[i] ='*', ++num;
return 1;
}
else {
for(int i = 1, num = 1; num <= xx; ++i)
if(px.cord[i] == 'K') px.cord[i] ='*', ++num;
for(int i = 1, num = 1; num <= xx+1; ++i)
if(py.cord[i] == 'K') py.cord[i] ='*', ++num;
return 0;
}
}
bool chupai(int num) {
zzz &p = pig[num];
//if(p.cord[p.pos] == '*') ++p.pos;
for(int l = 1; l <= p.tot; ++l) {
if(p.cord[l] == 'Z') {
printf("玩家%d装备了诸葛连弩\n", num);
p.cord[l] = '*', p.zgln = 1; return 1;
}
if(p.cord[l] == 'P' && p.hp < 4) {
printf("玩家%d 对自己使用了桃 ,现在剩余体力值为%d点\n ", num, pig[num].hp);
p.cord[l] = '*', ++p.hp; return 1;
}
// W N 联动
if(p.cord[l] == 'N') {
printf("玩家%d对全体玩家使用了南蛮入侵\n", num);
int cnt = num % n + 1; p.cord[l] = '*';
for(int i = cnt; i != num; i = i%n+1) {
if(pig[i].dead) continue; bool flag = 0;
if(pig[i].wszd) // 只能对跳身份的人献殷勤
if(wxkj(num, i, 0)) flag = 1;
if(flag) continue;
else printf("没有人对玩家%d使用无懈可击\n", i);
for(int j = 1; j <= pig[i].tot; ++j) {
if(pig[i].cord[j] == 'K') {
printf("玩家%d使用了一张杀\n", i);
pig[i].cord[j] = '*', flag = 1; break;
}
}
if(!flag) {
printf("玩家%d失去了一点体力\n", i);
--pig[i].hp;
if(pig[i].hp) printf("玩家%d的血量是 %d\n", i, pig[i].hp);
if(i == 1 && !p.wszd) p.lfz = 1;
}
if(!pig[i].hp) die(num, i);
}
return 1;
}
if(p.cord[l] == 'W') {
printf("玩家%d对全体玩家使用了万箭齐发\n", num);
int cnt = num % n + 1; p.cord[l] = '*';
for(int i = cnt; i != num; i = i%n+1) {
if(pig[i].dead) continue;
bool flag = 0;
if(pig[i].wszd) // 只能对跳身份的人献殷勤
if(wxkj(num, i, 0)) flag = 1;
if(flag) continue;
else printf("没有人对玩家%d使用无懈可击\n", i);
for(int j = 1; j <= pig[i].tot; ++j) {
if(pig[i].cord[j] == 'D') {
printf("玩家%d使用了一张闪\n", i);
pig[i].cord[j] = '*', flag = 1; break;
}
}
if(!flag) {
printf("玩家%d失去了一点体力\n", i);
--pig[i].hp;
if(pig[i].hp) printf("玩家%d的血量是 %d\n", i, pig[i].hp);
if(i == 1 && !p.wszd) p.lfz = 1;
}
if(!pig[i].hp) die(num, i);
}
return 1;
}
if(p.cord[l] == 'K') {
if(p.one && !p.zgln) return 0;
bool flag = 0;
int i = p.dis;
if(!pig[i].dead && godie(num, i)) {
printf("玩家%d对玩家%d使用了一张杀\n", num, i);
p.cord[l] = '*'; p.wszd = 1; p.one = 1; p.lfz = 0;
for(int j = 1; j <= pig[i].tot; ++j) {
if(pig[i].cord[j] == 'D') {
printf("玩家%d使用了一张闪\n", i);
pig[i].cord[j] = '*', flag = 1; break;
}
}
if(!flag) printf("玩家%d 受到了来自 玩家%d的杀的伤害\n", i, num), --pig[i].hp;
if(pig[i].hp) printf("玩家%d的血量是 %d\n", i, pig[i].hp);
if(!pig[i].hp) die(num, i);
return 1;
break;
}
}
if(p.cord[l] == 'F') {
int cnt = num % n + 1;
if(p.id == 3) {
int i = 1;
printf("玩家%d对玩家%d使用了一张决斗\n", num, i);
p.cord[l] = '*'; p.wszd = 1; p.lfz = 0;
if(pig[i].wszd && wxkj(num, i, 0)) break;
if(p.id == 1 && pig[i].lfz == 1 && pig[i].id == 2) {
printf("玩家%d决斗失败,失去一点血\n", i); --pig[i].hp; goto ree;
}
if(jd(num, i)) --pig[i].hp, printf("玩家%d决斗失败,失去一点血\n",i);
else --pig[num].hp, printf("玩家%d决斗失败,失去一点血\n", num);
ree:
if(pig[num].hp) printf("玩家%d的血量是 %d\n", num,pig[num].hp);
if(pig[i].hp) printf("玩家%d的血量是 %d\n", i,pig[i].hp);
if(!pig[i].hp) die(num, i);
if(!pig[num].hp) die(i, num);
return 1;
}
for(int i = cnt; i != num; i = i%n+1) {
if(!pig[i].dead && godie(num, i)) {
printf("玩家%d对玩家%d使用了一张决斗\n", num, i);
p.cord[l] = '*'; p.wszd = 1; p.lfz = 0;
if(wxkj(num, i, 0)) break;
if(p.id == 1 && pig[i].lfz == 1 && pig[i].id == 2) {
printf("玩家%d决斗失败,失去一点血\n", i);
--pig[i].hp; goto re;
}
if(jd(num, i)) --pig[i].hp, printf("玩家%d决斗失败,失去一点血\n",i);
else --pig[num].hp, printf("玩家%d决斗失败,失去一点血\n", num);
re:
if(pig[num].hp) printf("玩家%d的血量是 %d\n", num,pig[num].hp);
if(pig[i].hp) printf("玩家%d的血量是 %d\n", i,pig[i].hp);
if(!pig[i].hp) die(num, i);
if(!pig[num].hp) die(i, num);
return 1;
}
}
}
}
return 0;
}
int main() {
freopen("1.in", "r", stdin);
freopen("my.out", "w", stdout);
n = read(), m = read();
for(int i = 1; i <= n; ++i) {
char c[3]; cin >> c;
pig[i].hp = pig[i].tot = 4;
if(c[0] == 'M') pig[i].id = 1;
if(c[0] == 'Z') pig[i].id = 2;
if(c[0] == 'F') pig[i].id = 3, ++fp_num;
for(int j = 1; j <= 4; ++j) pig[i].cord[j] = read_c();
pig[i].dis = i % n + 1;
}
pig[1].wszd = 1;
for(int i = 1; i <= m; ++i) allc[i] = read_c();
int cnt = 0, tot = 0;
while(1) {
cnt = cnt % n + 1; zzz &p = pig[cnt];
if(p.dead) continue;
mopai(cnt, 2);
while(chupai(cnt)) {}
p.one = 0;
printf("回合%d结束\n", ++tot); printf("\n----------------------\n\n");
}
return 0;
}
AC代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#define LL long long
using namespace std;
LL read() {
LL k = 0, f = 1; char c = getchar();
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9')
k = k * 10 + c - 48, c = getchar();
return k * f;
}
char read_c() {
char c = getchar();
while ((c < 'a' || c > 'b') && (c < 'A' || c > 'Z')) c = getchar();
while ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) return c;
return c;
}
int n, m;
struct zzz {
int tot, hp, dis, id; // 手牌数量 血量 距离 身份:1=mp 2=zp 3=fp
bool lfz, zgln, wszd, dead, one; // 类反猪标志 诸葛连弩 表明身份 死亡 杀只能用一次
char cord[2010]; // 手牌
}pig[110];
char allc[2010]; int pos;
int fp_num;
void mopai(int num, int k) {
int &tot = pig[num].tot;
for(int i = 1; i <= k; ++i) {
if(pos == m) --pos;
pig[num].cord[++tot] = allc[++pos];
}
}
bool waf(int x, int y) { // 判断x是否会对y献殷勤
zzz &px = pig[x], &py = pig[y];
if(py.wszd && (px.id == py.id || (px.id == 2 && py.id == 1) || (px.id == 1 && py.id == 2))) return 1;
return 0;
}
bool godie(int x, int y){ // 判断x是否会对y表敌意
zzz &px = pig[x], &py = pig[y];
if(py.wszd && (px.id == 2 || px.id == 1) && py.id == 3) return 1;
if(py.wszd && px.id == 3 && (py.id == 1 || py.id == 2)) return 1;
if(py.lfz && px.id == 1) return 1;
return 0;
}
bool wxkj(int num, int k, int lx) {
for(int i = num, ii = 1; ii <= n; i = i%n+1, ++ii) {
if(!lx && waf(i, k)) {
for(int j = 1; j <= pig[i].tot; ++j) {
if(pig[i].cord[j] == 'J') {
pig[i].wszd = 1, pig[i].cord[j] = '*', pig[i].lfz = 0;
int cnt = i%n+1;
if(wxkj(cnt, k, lx^1)) return 0; else return 1;
}
}
}
if(lx && godie(i, k)) {
for(int j = 1; j <= pig[i].tot; ++j) {
if(pig[i].cord[j] == 'J') {
pig[i].wszd = 1, pig[i].cord[j] = '*', pig[i].lfz = 0;
int cnt = i%n+1;
if(wxkj(cnt, k, lx^1)) return 0; else return 1;
}
}
}
}
return 0;
}
void gameover(int flag) {
if(flag == 1) puts("MP");
else puts("FP");
for(int i = 1; i <= n; ++i) {
if(pig[i].dead) {
puts("DEAD"); continue;
}
for(int j = 1; j <= pig[i].tot; ++j) {
if(pig[i].cord[j] != '*') printf("%c ", pig[i].cord[j]);
}
printf("\n");
}
exit(0);
}
void die(int num, int vic) { // num 伤害来源, vic 濒死
zzz &p = pig[vic];
for(int i = 1; i <= p.tot; ++i) {
if(p.cord[i] == 'P') {
p.cord[i] = '*', ++p.hp; return ;
}
}
p.dead = 1;
for(int i = 1; i <= p.tot; ++i) p.cord[i] = '*';
if(p.id == 1) gameover(2); // 反猪胜利
if(p.id == 3) {
--fp_num; if(!fp_num) gameover(1); //主猪胜利
mopai(num, 3);
}
if(p.id == 2 && pig[num].id == 1) {
for(int i = 1; i <= pig[num].tot; ++i)
pig[num].cord[i] = '*';
pig[num].zgln = 0;
}
int ff = 0, fff = 0;
for(int i = n; i >= 1; --i) {
if(!pig[i].dead) pig[i].dis = ff;
if(!fff && !pig[i].dead) fff = i;
ff = i;
}
pig[fff].dis = 1;
}
bool jd(int x, int y) {
zzz &px = pig[x], &py = pig[y];
int xx = 0, yy = 0;
for(int i = 1; i <= px.tot; ++i)
if(px.cord[i] == 'K') ++xx;
for(int i = 1; i <= py.tot; ++i)
if(py.cord[i] == 'K') ++yy;
if(xx >= yy) {
for(int i = 1, num = 1; num <= yy; ++i)
if(px.cord[i] == 'K') px.cord[i] ='*', ++num;
for(int i = 1, num = 1; num <= yy; ++i)
if(py.cord[i] == 'K') py.cord[i] ='*', ++num;
return 1;
}
else {
for(int i = 1, num = 1; num <= xx; ++i)
if(px.cord[i] == 'K') px.cord[i] ='*', ++num;
for(int i = 1, num = 1; num <= xx+1; ++i)
if(py.cord[i] == 'K') py.cord[i] ='*', ++num;
return 0;
}
}
bool chupai(int num) {
zzz &p = pig[num];
//if(p.cord[p.pos] == '*') ++p.pos;
for(int l = 1; l <= p.tot; ++l) {
if(p.cord[l] == 'Z') {
p.cord[l] = '*', p.zgln = 1; return 1;
}
if(p.cord[l] == 'P' && p.hp < 4) {
p.cord[l] = '*', ++p.hp; return 1;
}
// W N 联动
if(p.cord[l] == 'N') {
int cnt = num % n + 1; p.cord[l] = '*';
for(int i = cnt; i != num; i = i%n+1) {
if(pig[i].dead) continue; bool flag = 0;
if(pig[i].wszd) // 只能对跳身份的人献殷勤
if(wxkj(num, i, 0)) flag = 1;
if(flag) continue;
for(int j = 1; j <= pig[i].tot; ++j) {
if(pig[i].cord[j] == 'K') {
pig[i].cord[j] = '*', flag = 1; break;
}
}
if(!flag) {
--pig[i].hp;
if(i == 1 && !p.wszd) p.lfz = 1;
}
if(!pig[i].hp) die(num, i);
}
return 1;
}
if(p.cord[l] == 'W') {
int cnt = num % n + 1; p.cord[l] = '*';
for(int i = cnt; i != num; i = i%n+1) {
if(pig[i].dead) continue;
bool flag = 0;
if(pig[i].wszd) // 只能对跳身份的人献殷勤
if(wxkj(num, i, 0)) flag = 1;
if(flag) continue;
for(int j = 1; j <= pig[i].tot; ++j) {
if(pig[i].cord[j] == 'D') {
pig[i].cord[j] = '*', flag = 1; break;
}
}
if(!flag) {
--pig[i].hp;
if(i == 1 && !p.wszd) p.lfz = 1;
}
if(!pig[i].hp) die(num, i);
}
return 1;
}
if(p.cord[l] == 'K') {
if(p.one && !p.zgln) continue;
bool flag = 0;
int i = p.dis;
if(!pig[i].dead && godie(num, i)) {
p.cord[l] = '*'; p.wszd = 1; p.one = 1; p.lfz = 0;
for(int j = 1; j <= pig[i].tot; ++j) {
if(pig[i].cord[j] == 'D') {
pig[i].cord[j] = '*', flag = 1; break;
}
}
if(!flag) --pig[i].hp;
if(!pig[i].hp) die(num, i);
return 1;
break;
}
}
if(p.cord[l] == 'F') {
int cnt = num % n + 1;
if(p.id == 3) {
int i = 1;
p.cord[l] = '*'; p.wszd = 1; p.lfz = 0;
if(pig[i].wszd && wxkj(num, i, 0)) break;
if(p.id == 1 && pig[i].lfz == 1 && pig[i].id == 2) {
--pig[i].hp; goto ree;
}
if(jd(num, i)) --pig[i].hp;
else --pig[num].hp;
ree:
if(!pig[i].hp) die(num, i);
if(!pig[num].hp) die(i, num);
return 1;
}
for(int i = cnt; i != num; i = i%n+1) {
if(!pig[i].dead && godie(num, i)) {
p.cord[l] = '*'; p.wszd = 1; p.lfz = 0;
if(wxkj(num, i, 0)) break;
if(p.id == 1 && pig[i].lfz == 1 && pig[i].id == 2) {
--pig[i].hp; goto re;
}
if(jd(num, i)) --pig[i].hp;
else --pig[num].hp;
re:
if(!pig[i].hp) die(num, i);
if(!pig[num].hp) die(i, num);
return 1;
}
}
}
}
return 0;
}
int main() {
n = read(), m = read();
for(int i = 1; i <= n; ++i) {
char c[3]; cin >> c;
pig[i].hp = pig[i].tot = 4;
if(c[0] == 'M') pig[i].id = 1;
if(c[0] == 'Z') pig[i].id = 2;
if(c[0] == 'F') pig[i].id = 3, ++fp_num;
for(int j = 1; j <= 4; ++j) pig[i].cord[j] = read_c();
pig[i].dis = i % n + 1;
}
pig[1].wszd = 1;
for(int i = 1; i <= m; ++i) allc[i] = read_c();
int cnt = 0;
while(1) {
cnt = cnt % n + 1; zzz &p = pig[cnt];
if(p.dead) continue;
mopai(cnt, 2);
while(chupai(cnt)) {}
p.one = 0;
}
return 0;
}