題目大意:ios
給出一個合乎規則的象棋殘局,棋盤上黑方只有將,紅方已經「delivered a check」。要求判斷紅方可否把黑方「checkmate」。c++
思路:函數
1. 維護一個矩陣表示棋盤上紅方棋子的佈局;佈局
2. 維護一個vector存儲紅方的棋子的位置,以便於後續訪問;測試
3. 模擬黑將走一步的過程,對於每一個黑將可能走的位置,判斷黑將是否會被吃掉。若是全部能走的位置上黑將都會被吃掉,那麼輸出YES。若是存在一個位置使黑將逃脫,輸出NO。spa
坑點:code
1. 黑將走到下一步時也能夠吃掉紅方。blog
2. 雖然黑方在初始位置能夠不被吃,但此時已經輪到黑方走,黑將必須走一步,不能停在原地。假如全部能走到的地方都會被吃,黑方還是要輸的。ci
3. 衆所周知,uDebug上的數據極可能是有坑的。it
特別地,對比車和炮的規則發現,炮在行進路線上能且只能跳過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 }