题意
n*n的棋盘中,有三个国际象棋棋子,分别是黑王,黑兵,白兵。
规定:
如果白兵到底线升变,白方胜
如果黑王被吃,白方胜
如果黑兵到达底线,可以升变。
如果白兵无法移动或被吃,黑方胜。
王、兵移动规则与吃子规则完全模仿国际象棋
问:残局下,谁胜
题解
坑比题。
不计其数的卡,比如王卡象,王卡兵,王卡车,另外还有兵卡王。
注意过路兵这个设定是存在的
比较恶心的在于,白兵可以选择不吃黑兵,直接向前。。。
如果想要少考虑些,可以思考写成DP
但DP也难写,更重要的一点是:白方是具有决策的,而且是有两种:开始走两步以及吃与不吃
剩下的就是一个BFS了
code
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <string>
#include <vector>
typedef long long LL;
const int dxy[8][2] = {{1, 0}, {1, 1}, {0, 1}, {-1, 1}, {-1, 0}, {-1, -1}, {0, -1}, {1, -1}};
const int maxn = 30;
const int maxQ = 6000010;
int n;
struct Point {
char x, y;
};
struct Node {
Point wp, bp, bk; bool col;
};
Point wp, bp, bk;
Point _wp, _bp, _bk;
Node Q[maxQ]; int l, r;
bool check(int x, int y) { return 1 <= x && x <= n && 1 <= y && y <= n; }
std::set<LL> inq;
LL encode(const Node& A) {
return ((((((LL)A.wp.x*30+A.wp.y)*30+A.bp.x)*30+A.bp.y)*30+A.bk.x)*30+A.bk.y)*2 + A.col;
}
void push_Q(const Node& A) {
int x = encode(A);
if (inq.count(x)) return;
inq.insert(x);
Q[r ++] = A; if (r == maxQ) r = 0;
}
bool white(bool eat, bool fly) {
l = r = 0; inq.clear();
push_Q((Node){_wp, _bp, _bk, 0});
for (; l != r; l = (l+1 == maxQ ? 0 : l+1)) {
Node u = Q[l]; wp = u.wp, bp = u.bp, bk = u.bk;
// printf("%d %d %d %d %d %d\n", wp.x, wp.y, bp.x, bp.y, bk.x, bk.y);
if (u.wp.y == n) continue;
if (u.col == 0) {
if (std::abs(bk.x-wp.x) == 1 && bk.y == wp.y + 1) continue;
if (fly && wp.y == 2) {
if (!(bp.x == wp.x && bp.y == wp.y+1) && !(bk.x == wp.x && bk.y == wp.y+1)) {
if (!(bp.x == wp.x && bp.y == wp.y+2) && !(bk.x == wp.x && bk.y == wp.y+2) && !(std::abs(bp.x-wp.x) == 1 && bp.y == wp.y+2)) {
wp.y += 2; push_Q((Node){wp, bp, bk, 1}); wp.y -= 2;
continue;
}
} else
return 0;
}
if (eat && std::abs(bp.x-wp.x) == 1 && bp.y == wp.y + 1) { push_Q((Node){(Point){bp.x, bp.y}, (Point){-1, -1}, bk, 1}); continue; }
if (!(bp.x == wp.x && bp.y == wp.y+1) && !(bk.x == wp.x && bk.y == wp.y+1)) {
++ wp.y; push_Q((Node){wp, bp, bk, 1}); -- wp.y;
} else
return 0;
} else {
if (bp.x != -1) {
if (bp.y == 1) {
if (wp.y+1 < n) { return 0; }
if ((wp.x == bp.x+1 && wp.y == bp.y+2) || (wp.x == bp.x+2 && wp.y == bp.y+1) ||
(wp.x == bp.x-1 && wp.y == bp.y+2) || (wp.x == bp.x-2 && wp.y == bp.y+1)) { return 0; }
if (wp.x == bp.x && !(bk.x == bp.x && bp.y <= bk.y && bk.y <= wp.y))
return 0;
if (wp.x < bp.x && !(bk.y-bp.y == bp.x-bk.x) && (wp.y <= bp.y + (bp.x-wp.x))) return 0;
if (wp.x > bp.y && !(bk.y-bp.y == bk.x-bp.x) && (wp.y <= bp.y + (wp.x-bp.x))) return 0;
} else {
if (std::abs(wp.x-bp.x) == 1 && wp.y == bp.y-1) { return 0; }
if (!(wp.x == bp.x && wp.y == bp.y-1) && !(bk.x == bp.x && bk.y == bp.y-1)) {
if ((wp.x != bp.x || wp.y != bp.y-2) && bp.y == n-1 && !(std::abs(wp.x-bp.x) == 1 && wp.y == bp.y-2)) { bp.y -= 2; push_Q((Node){wp, bp, bk, 0}); bp.y += 2; }
-- bp.y; push_Q((Node){wp, bp, bk, 0}); ++ bp.y;
}
}
}
if (std::abs(wp.x-bk.x) <= 1 && std::abs(wp.y-bk.y) <= 1) { return 0; }
for (int d = 0; d < 8; ++ d) {
int X = bk.x + dxy[d][0], Y = bk.y + dxy[d][1];
if (!(bp.x == X && bp.y == Y) && check(X, Y)) { push_Q((Node){wp, bp, (Point){X, Y}, 0}); }
}
}
}
return 1;
}
void solve() {
int t1, t2, t3;
scanf("%d %c%d %c%d %c%d", &n, &wp.x, &t1, &bp.x, &t2, &bk.x, &t3);
wp.x -= 'a'-1; bp.x -= 'a'-1; bk.x -= 'a'-1;
wp.y = t1, bp.y = t2, bk.y = t3;
_wp = wp; _bp = bp; _bk = bk;
// printf("%d\n", white(1, 1));
// printf("%d\n", white(1, 0));
// printf("%d\n", white(0, 1));
// printf("%d\n", white(0, 0));
if (white(1, 1) || white(1, 0) || white(0, 1) || white(0, 0)) puts("WHITE WINS"); else puts("BLACK WINS");
}
int main() {
// freopen("A.in", "r", stdin);
// freopen("A.out", "w", stdout);
// for (int i = 1; i <= 16; ++ i)
solve();
// for(;;);
return 0;
}