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;
}


posted @ 2015-01-31 14:12  Popco  阅读(155)  评论(0编辑  收藏  举报