本题存在吃子的陷阱,为了跳过吃子陷阱,考虑对于红子不处理它本身的坐标,留给其他子处理。解题思路为用二维数字组m1存红子坐标,m2表示红子所能管辖的点。
分别处理车、马、炮、帅的管辖范围。具体代码如下:
#include <iostream> #include <cstring> using namespace std; int m1[13][13], m2[13][13], n, gx, gy; void general(int x, int y) { for (int i = x - 1; i > 0; i--) { if (m1[i][y] != 0 && i > 3) break; if (i < 4) { m2[i][y]++; if (m1[i][y] != 0) break; } } } void chariot(int x, int y) { int i = 0; for (i = x + 1; i < 11; i++) { m2[i][y]++; if (m1[i][y] != 0) break; } for (i = x - 1; i > 0; i--) { m2[i][y]++; if (m1[i][y] != 0) break; } for (i = y + 1; i < 10; i++) { m2[x][i]++; if (m1[x][i] != 0) break; } for (i = y - 1; i > 0; i--) { m2[x][i]++; if (m1[x][i] != 0) break; } } void cannon(int x, int y) { int flag, i; flag = 0; for (i = x + 1; i < 11; i++) { if (flag) { m2[i][y]++; if (m1[i][y]) break; } if (flag == 0 && m1[i][y] != 0) flag = 1; } flag = 0; for (i = x - 1; i > 0; i--) { if (flag) { m2[i][y]++; if (m1[i][y]) break; } if (flag == 0 && m1[i][y] != 0) flag = 1; } flag = 0; for (i = y + 1; i < 10; i++) { if (flag) { m2[x][i]++; if (m1[x][i]) break; } if (flag == 0 && m1[x][i] != 0) flag = 1; } flag = 0; for (i = y - 1; i > 0; i--) { if (flag) { m2[x][i]++; if (m1[x][i]) break; } if (flag == 0 && m1[x][i] != 0) flag = 1; } } void horse(int x, int y) { if (x > 2 && m1[x - 1][y] == 0) { if (y > 1) m2[x - 2][y - 1]++; if (y < 9) m2[x - 2][y + 1]++; } if (x < 9 && m1[x + 1][y] == 0) { if (y > 1) m2[x + 2][y - 1]++; if (y < 9) m2[x + 2][y + 1]++; } if (y > 2 && m1[x][y - 1] == 0) { if (x > 1) m2[x - 1][y - 2]++; if (x < 10) m2[x + 1][y - 2]++; } if (y < 8 && m1[x][y + 1] == 0) { if (x > 1) m2[x - 1][y + 2]++; if (x < 10) m2[x + 1][y + 2]++; } } int judge() { int res = 1; if (gx > 1 && m2[gx - 1][gy] == 0) res = 0; if (gx < 3 && m2[gx + 1][gy] == 0) res = 0; if (gy > 4 && m2[gx][gy - 1] == 0) res = 0; if (gy < 6 && m2[gx][gy + 1] == 0) res = 0; return res; } int main() { //freopen("input1.in", "rw", stdin); //freopen("output1.in", "w", stdout); int red[10][3]; char cmd[5]; while (cin >> n >> gx >> gy && n) { memset(m1, 0, sizeof(m1)); memset(m2, 0, sizeof(m2)); for (int i = 0; i < n; i++) { cin >> cmd >> red[i][1] >> red[i][2]; red[i][0] = cmd[0]; m1[red[i][1]][red[i][2]] = cmd[0]; } for (int i = 0; i < n; i++) { if (red[i][0] == 'G') general(red[i][1], red[i][2]); if (red[i][0] == 'R') chariot(red[i][1], red[i][2]); if (red[i][0] == 'C') cannon(red[i][1], red[i][2]); if (red[i][0] == 'H') horse(red[i][1], red[i][2]); } if (judge()) cout << "YES" << endl; else cout << "NO" << endl; } return 0; }
网上找的生成测试数据的代码如下:
#include<cstdio> #include<cstring> #include<algorithm> #include<ctime> using namespace std; int main() { freopen("input1.in", "w", stdout); srand(unsigned(time(0))); int maxn = 6, count = 0; int dir[11][10]; int keep = 1; const char s0[] = "RRCCHH"; for (int s = (1<<maxn) - 1; s >= 1; s--) for (int num = 1000; num; num--) { printf("%d\n",keep++); memset(dir, 0, sizeof(dir)); int n = 0, is = 0; int r0 = 1 + rand() % 3, c0 = 4 + rand() % 3;//黑棋将的位置 dir[r0][c0] = 1; int r1 = 8 + rand() % 3, c1 = 4 + rand() % 3;//红棋将的位置 while (c0 == c1)//目的是使黑红两将不在同一竖直位置 c1 = 4 + rand() % 3; dir[r1][c1] = 1; for (int i = 0; i < maxn; i++)//n值从6至1开始变化 if (s & (1<<i)) n++; printf("\n%d %d %d\nG %d %d\n",n + 1, r0, c0, r1, c1);//打印第一行,第二行 count++; for (int i = 0; i < maxn; i++) if (s & (1<<i)) { int r = 1 + rand() % 10, c = 1 + rand() % 9;//车马炮位置 if (is == 0 && s0[i] != 'C') { if (s0[i] != 'H')//车 { r = r0 + 1; c = c0; //printf("车%c\n",s0[i]); } else//马 { r = r0 + 2; c = c0 + 1; //printf("马%c\n",s0[i]); } is = 1; } else//炮车马 { while (dir[r][c]) { r = 1 + rand() % 10; c = 1 + rand() % 9; } //printf("炮车马%c\n",s0[i]); } dir[r][c] = 1; printf("%c %d %d\n", s0[i], r, c); } } printf("0 0 0\n"); return 0; }