UVa 1589 - Xiangqi <细节基础题>
这个题,三个月前写了一次,当时写道200行的时候,就感觉恶心了,当时感觉再写100行也完不成。
今天拿出这题来重写了,尽量精简代码,结果没想到90行就AC了。精简代码的好处之一便是方便调试,因为细节太多了,把很多相似的内容放在函数中就好了。
看似四个棋子的走法不同,实则有一个共同点:都需要判断棋子和“将”所在的行或者列中,两个棋子之间的棋子数。对于“帅”和“车”,之间的棋子数必须为0。对于炮,之间的棋子数必须为1。对于马,可以利用这一点判断是否有憋马脚的情况。
其他需要注意的点:
1.初始棋盘中,如果将帅正对,那么红方必败。
2.红方棋子有可能被将吃掉,需要处理。
#include <bits/stdc++.h> using namespace std; struct One{ int r, c; char type; }; One Red[10]; int N, r0, c0, G_NO; char tab[12][12]; const int dir[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}}; const int Hdir[8][4] = { {-1, 2, 0, 2}, {1, 2, 0, 2}, {-2, -1, -2, 0}, {-2, 1, -2, 0}, {-1, -2, 0, -2}, {1, -2, 0, -2}, {2, -1, 2, 0}, {2, 1, 2, 0} }; inline bool in_black_palace(const int r, const int c){ return r >= 1 && r <= 3 && c >= 4 && c <= 6; } int get_range_block(int r1, int c1, int r2, int c2){ int cnt = 0; if(r1 != r2 && c1 != c2) return -1; if(r1 == r2){ if(c1 > c2) swap(c1, c2); for(int i = c1 + 1; i <= c2 - 1; ++i) if(tab[r1][i] != '\0') cnt++; } else if(c1 == c2){ if(r1 > r2) swap(r1, r2); for(int i = r1 + 1; i <= r2 - 1; ++i) if(tab[i][c1] != '\0') cnt++; } return cnt; } bool G(const int r, const int c, const int x, const int y){ if(c != y) return false; return get_range_block(r, c, x, y) == 0; } bool R(const int r, const int c, const int x, const int y){ int res = get_range_block(r, c, x, y); if(res == -1) return false; return res == 0; } bool H(const int r, const int c, const int x, const int y){ for(int i = 0; i < 8; ++i){ int x1 = x + Hdir[i][0], y1 = y + Hdir[i][1]; if(x1 == r && y1 == c && get_range_block(x, y, x + Hdir[i][2], y + Hdir[i][3])==0) return true; } return false; } bool C(const int r, const int c, const int x, const int y){ int res = get_range_block(r, c, x, y); if(res == -1) return false; return res == 1; } bool check_red_win(const int r, const int c){ for(int i = 0; i < N; ++i) if(!(Red[i].r==r && Red[i].c==c)){ One & t = Red[i]; if(t.type == 'G' && G(r, c, t.r, t.c)) return true; if(t.type == 'R' && R(r, c, t.r, t.c)) return true; if(t.type == 'H' && H(r, c, t.r, t.c)) return true; if(t.type == 'C' && C(r, c, t.r, t.c)) return true; } return false; } int main() { ios::sync_with_stdio(false); while(memset(Red, 0, sizeof(Red)), memset(tab, 0, sizeof(tab)), cin >> N >> r0 >> c0, !(N==0 && r0==0 && c0==0)){ for(int i = 0; i < N; i++){ One t; cin >> t.type >> t.r >> t.c; if(t.type=='G') G_NO = i; tab[t.r][t.c] = t.type; Red[i] = t; } if(G(r0, c0, Red[G_NO].r, Red[G_NO].r)) {puts("NO"); continue;} bool red_win = true; for(int i = 0; i < 4; ++i){ int r1 = r0 + dir[i][0], c1 = c0 + dir[i][1]; if(in_black_palace(r1, c1) && !check_red_win(r1, c1)) {red_win = false; break;} } if(red_win) puts("YES"); else puts("NO"); } return 0; }