题解:P11878 城堡中的皇后
主要思路
一道没有什么思路难度的大模拟(打磨你)。
对于棋盘记录,
对于 FEN 到棋盘的转换,可以每一部分,可以记录一个
转换完成后,遍历棋盘,只要这个位置有棋子并且不是王,就判断当前棋子是否能将军对面的王;如果所有棋子都不能,就输出 none。
AC Code
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef long double db;
const int INT_INF = 0x3f3f3f3f;
const ll LL_INF = 0x3f3f3f3f3f3f3f3f;
inline ll _abs(ll a) { if (a < 0) return -a; return a; }
const int dx[8] = {-1, -2, -2, -1, 1, 2, 2, 1}, dy[8] = {-2, -1, 1, 2, 2, 1, -1, -2};
// ----------------------------
// ----------------------------
int board[10][10];
// ----------------------------
bool pawn(int x, int y, int f) {
if (f == 1) {
return (board[x - 1][y - 1] == -6 || board[x - 1][y + 1] == -6);
}
return (board[x + 1][y - 1] == 6 || board[x + 1][y + 1] == 6);
}
bool knight(int x, int y, int f) {
int nx, ny;
for (int i = 0; i < 8; i++) {
nx = x + dx[i];
ny = y + dy[i];
if (board[nx][ny] == 6 * -f) return true;
}
return false;
}
bool bishop(int x, int y, int f) {
int nx = x - 1;
int ny = y - 1;
while (nx > 0 && ny > 0 && board[nx][ny] == 0) {
nx--;
ny--;
} // 找到斜线上第一个棋子
if (board[nx][ny] == 6 * -f) return true;
nx = x - 1;
ny = y + 1;
while (nx > 0 && ny <= 8 && board[nx][ny] == 0) {
nx--;
ny++;
}
if (board[nx][ny] == 6 * -f) return true;
nx = x + 1;
ny = y - 1;
while (nx <= 8 && ny > 0 && board[nx][ny] == 0) {
nx++;
ny--;
}
if (board[nx][ny] == 6 * -f) return true;
nx = x + 1;
ny = y + 1;
while (nx <= 8 && ny <= 8 && board[nx][ny] == 0) {
nx++;
ny++;
}
if (board[nx][ny] == 6 * -f) return true;
return false;
}
bool rook(int x, int y, int f) {
int nx = x - 1;
int ny = y;
while (nx > 0 && board[nx][ny] == 0) nx--; // 找到直线上第一个棋子
if (board[nx][ny] == 6 * -f) return true;
nx = x + 1;
ny = y;
while (nx <= 8 && board[nx][ny] == 0) nx++;
if (board[nx][ny] == 6 * -f) return true;
nx = x;
ny = y - 1;
while (ny > 0 && board[nx][ny] == 0) ny--;
if (board[nx][ny] == 6 * -f) return true;
nx = x;
ny = y + 1;
while (ny <= 8 && board[nx][ny] == 0) ny++;
if (board[nx][ny] == 6 * -f) return true;
return false;
}
int transform(char c) {
if (c == 'P') return 1;
if (c == 'N') return 2;
if (c == 'B') return 3;
if (c == 'R') return 4;
if (c == 'Q') return 5;
if (c == 'K') return 6;
if (c == 'p') return -1;
if (c == 'n') return -2;
if (c == 'b') return -3;
if (c == 'r') return -4;
if (c == 'q') return -5;
if (c == 'k') return -6;
return 0;
}
void write(bool f) {
if (f) cout << "CHECK\n";
else cout << "check\n";
}
int main() {
int t; cin >> t;
// ----------------------------
bool flag;
string fen;
int idx, col;
while (t--) {
cin >> fen;
idx = -1;
memset(board, 0, sizeof board);
for (int i = 1; i <= 8; i++) {
idx++;
col = 1;
while (idx < (int)fen.length() && fen[idx] != '/') {
if (isdigit(fen[idx])) col += fen[idx] - '0';
else board[i][col++] = transform(fen[idx]);
idx++;
}
}
flag = false;
for (int i = 1; i <= 8 && !flag; i++) {
for (int j = 1; j <= 8; j++) {
if (_abs(board[i][j]) == 1) { // 判断这个棋子是否为兵,白黑都可以
if (pawn(i, j, board[i][j] / _abs(board[i][j]))) {
flag = true;
write(board[i][j] > 0);
break;
}
}
else if (_abs(board[i][j]) == 2) {
if (knight(i, j, board[i][j] / _abs(board[i][j]))) {
flag = true;
write(board[i][j] > 0);
break;
}
}
else if (_abs(board[i][j]) == 3) {
if (bishop(i, j, board[i][j] / _abs(board[i][j]))) {
flag = true;
write(board[i][j] > 0);
break;
}
}
else if (_abs(board[i][j]) == 4) {
if (rook(i, j, board[i][j] / _abs(board[i][j]))) {
flag = true;
write(board[i][j] > 0);
break;
}
}
else if (_abs(board[i][j]) == 5) { // 后就是结合了象与车的走法,所以不需要单独再写一个函数
if (bishop(i, j, board[i][j] / _abs(board[i][j])) ||
rook(i, j, board[i][j] / _abs(board[i][j]))) {
flag = true;
write(board[i][j] > 0);
break;
}
}
}
}
if (!flag) cout << "none\n";
}
return 0;
}