UVa1589 Xiangqi 坑点总结+参考代码

题目大意:

  

  给出一个合乎规则的象棋残局,棋盘上黑方只有将,红方已经“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 }

 

上一篇:汇编语言实现通过8255A和4个开关控制实现8个LED灯和8个7位数码管显示指定数字全亮、全灭、从左至右、从右至左跑马灯式点亮


下一篇:汇编学习