题目大意:
给出一个合乎规则的象棋残局,棋盘上黑方只有将,红方已经“delivered a check”。要求判断红方能否把黑方“checkmate”。
思路:
1. 维护一个矩阵表示棋盘上红方棋子的布局;
2. 维护一个vector存储红方的棋子的位置,以便于后续访问;
3. 模拟黑将走一步的过程,对于每个黑将可能走的位置,判断黑将是否会被吃掉。如果所有能走的位置上黑将都会被吃掉,那么输出YES。如果存在一个位置使黑将逃脱,输出NO。
坑点:
1. 黑将走到下一步时也可以吃掉红方。
2. 虽然黑方在初始位置可以不被吃,但此时已经轮到黑方走,黑将必须走一步,不能停在原地。假如所有能走到的地方都会被吃,黑方仍是要输的。
3. 众所周知,uDebug上的数据很可能是有坑的。
特别地,对比车和炮的规则发现,炮在行进路线上能且只能跳过1个棋子,而车在路线上不能跳棋子(即能跳0个棋子),除此之外,规则的其它部分是相同的。因此完全可以把车和炮封装到同一函数chariot()上,唯一的区别在于能跳0还是1个棋子,具体调用见第66行和71行的代码。
AC代码如下(C++)
1 #include <bits/stdc++.h> 2 #define N 11 3 #define mp(x,y) make_pair(x,y) 4 #define fi() first 5 #define se() second 6 using namespace std; 7 char mat[N][N]; 8 vector<pair<int,int> > rds; 9 const int mv[][2] = {{-1,0},{1,0},{0,1},{0,-1}}; 10 const int mv2[4][2][2] = { 11 {{-1,-1},{-1,1}}, 12 {{1,-1},{1,1}}, 13 {{-1,1},{1,1}}, 14 {{-1,-1},{1,-1}} 15 }; 16 17 // 18 // 判断车/炮(x,y)能否将黑将(bx,by)吃掉 19 // 20 inline bool chariot(int bx,int by, int x,int y, int cc) { 21 int cnt=0; 22 if(x==bx) { 23 for(int i=min(by,y)+1; i<max(by,y); ++i) { 24 if(mat[x][i] != 0) { 25 ++cnt; 26 } 27 } 28 if(cnt==cc) return false; 29 } else if (y==by) { 30 for(int i=min(bx,x)+1; i<max(bx,x); ++i) { 31 if(mat[i][y] != 0) { 32 ++cnt; 33 } 34 } 35 if(cnt==cc) return false; 36 } 37 return true; 38 } 39 40 inline bool inbnd(int r, int c) { 41 return !(r<1||r>10 || c<1||c>9); 42 } 43 44 // 45 // 判断黑将在(bx,by)上是否危险 46 // 47 bool judge(int bx, int by) { 48 for(size_t i=0;i<rds.size();++i) { 49 int x = rds[i].fi(); 50 int y = rds[i].se(); 51 if(x==bx&&y==by) continue; 52 switch(mat[x][y]) { 53 case 'G': 54 if(y==by) { 55 int i; 56 for(i=bx+1; i<x; ++i) { 57 if(mat[i][y] != 0) { 58 break; 59 } 60 } 61 if(i==x) return false; 62 } 63 break; 64 case 'R': 65 if(x==bx || y==by) { 66 if(!chariot(bx,by,x,y, 0)) return false; 67 } 68 break; 69 case 'C': 70 { 71 if(!chariot(bx,by,x,y, 1)) return false; 72 } 73 break; 74 case 'H': 75 for(int i=0;i<4;++i) { 76 int nx1=x+mv[i][0], ny1=y+mv[i][1]; 77 if(inbnd(nx1,ny1) && mat[nx1][ny1]==0 && nx1!=bx&&ny1!=by) { 78 for(int j=0;j<2;++j) { 79 int nx2=nx1+mv2[i][j][0], ny2=ny1+mv2[i][j][1]; 80 if(nx2==bx && ny2==by) { 81 return false; 82 } 83 } 84 } 85 } 86 break; 87 } 88 } 89 return true; 90 } 91 92 // 93 // 求解单个测试用例 94 // 95 const char *solve(int bx, int by) { 96 for(int i=0;i<4;++i) { 97 int nx=bx+mv[i][0], ny=by+mv[i][1]; 98 if(nx<1||nx>3 || ny<4||ny>6) continue; 99 if(judge(nx,ny)) { 100 return "NO"; 101 } 102 } 103 return "YES"; 104 } 105 106 int main(void) { 107 ios::sync_with_stdio(false); 108 int n,xb,yb; 109 while((cin>>n>>xb>>yb) && (n&&xb&&yb)) { 110 memset(mat, 0, sizeof mat); 111 rds.clear(); 112 113 while(n--) { 114 char typ; int x,y; 115 cin>>typ>>x>>y; 116 mat[x][y] = typ; 117 rds.push_back(mp(x,y)); 118 } 119 120 cout<<solve(xb, yb)<<endl; 121 } 122 return 0; 123 }