UVa1589 象棋(Xiangqi)

主要考虑两点:
1. 不管红方还是黑方可以飞将(若两将间有棋子就不行)
2. 攻击的点9个,不管9个点红方有没有棋子只要红方能攻到就记录
比如下面这个图红方(8,4)可以攻击点(2,4),虽然点(2,4)有红方的棋子(车)但应把这个点记录下来, 表示黑将不能吃点(2,4)的车
主要的两点考虑进去了就行(该图红方可以将死)


参考代码如下:

#include 
using namespace std;
const char* s = "GRCH";
const int f1[] = { -2, -2,  2,  2, -1,  1, -1,  1 };
const int g1[] = { -1,  1, -1,  1, -2, -2,  2,  2 };
const int f[] = { -1,  1,  0,  0 };
const int g[] = {  0,  0, -1,  1 };
const int M = 10, N = 9;
int plat[M + 1][N + 1];
bool isVisit[M + 1][N + 1];
bool isExist(int x, int y) {
    return x > 0 && x <= M && y > 0 && y <= N;
}
bool isAttack(int x, int y) {
    return x >= 1 && x <= 3 && y >= 4 && y <= 6;
}

//Horse
void horseAttact(int x, int y) {
    for (int i = 0; i < 4; ++i) {
        int fx = x + f[i], gy = y + g[i];
        if (isExist(fx, gy) && !plat[fx][gy]) {
            int a = x + f1[i * 2], b = y + g1[i * 2];
            int c = x + f1[i * 2 + 1], d = y + g1[i * 2 + 1];
            if (isAttack(a, b)) isVisit[a][b] = true;
            if (isAttack(c, d)) isVisit[c][d] = true;
        }
    }
}
//Chariot
void chariotAttack(int x, int y) {
    for (int i = 0; i < 4; ++i) {
        int a = f[i], b = g[i];
        int fx = x + a, gy = y + b;
        while (isExist(fx, gy)) {
            if (isAttack(fx, gy)) isVisit[fx][gy] = true;
            if (plat[fx][gy]) break;
            fx += a;
            gy += b;
        }
    }
}
//Cannon
void cannonAttack(int x, int y) {
    for (int i = 0; i < 4; ++i) {
        int a = f[i], b = g[i];
        int fx = x + a, gy = y + b;
        while (isExist(fx, gy) && !plat[fx][gy]) {
            fx += a;
            gy += b;
        }
        fx += a;
        gy += b;
        while (isExist(fx, gy)) {
            if (isAttack(fx, gy)) isVisit[fx][gy] = true;
            if (plat[fx][gy]) break;
            fx += a;
            gy += b;
        }
    }
}
//Red General flying general
void redGeneralAttack(int x, int y) {
    for (int i = x - 1; i > 0; --i) {
        if (isAttack(i, y)) isVisit[i][y] = true;
        if (plat[i][y]) return;
    }
}
//Black General flying general
//If the Black General can fly, return false
bool blackGeneralAttack(int blackX, int redX, int y) {
    for (int i = blackX + 1; i < redX; ++i)
        if (plat[i][y]) return true;
    return false;
}
void (*attack[])(int, int) = { 0, chariotAttack, cannonAttack, horseAttact };
int main() {
    int n, blackX, blackY, redX, redY, c, x, y;
    while (scanf("%d%d%d", &n, &blackX, &blackY), n) {
        memset(plat, 0, sizeof(plat));
        memset(isVisit, 0, sizeof(isVisit));
        while (n--) {
            while ((c = getchar()) && isspace(c)) ;
            scanf("%d%d", &x, &y);
            if (c == s[0]) { redX = x; redY = y; }
            else for (int i = 1; i < 4; ++i)
                if (c == s[i]) { plat[x][y] = i; break; }
        }
        for (int i = 1; i <= M; ++i)
            for (int j = 1; j <= N; ++j)
                for (int k = 1; k < 4; ++k)
                    if (plat[i][j] == k) (*attack[k])(i, j);
        redGeneralAttack(redX, redY);
        bool ok = true;
        if (redY == blackY) ok = blackGeneralAttack(blackX, redX, redY);
        for (int i = 0; i < 4; ++i) {
            int fx = blackX + f[i], gy = blackY + g[i];
            if (isAttack(fx, gy) && !isVisit[fx][gy]) { ok = false; break; }
        }
        printf("%s\n", ok ? "YES" : "NO");
    }
    return 0;
}

你可能感兴趣的:(UVa)