题解:P11878 城堡中的皇后
原题链接
分析
本题为大模拟,只要有耐心就能过。
其实,题目已经把绝大多数解题需要的信息告诉我们了,只需按题意模拟即可。
-
首先,找出两方国王
k 和K 的位置,并存储进变量中。 -
然后,判断此时国王是否受对方棋子的攻击。
攻击判定方法如下:
- 判断国王的斜对角方向是否有对方的象或皇后;
- 判断国王的竖直方向及水平方向上是否有对方的车或皇后;
- 判断国王前方斜对角一格内是否有对方的兵;
- 判断国王是否受马攻击;
- 判断国王周围一圈内是否有对方的国王。
-
最后,若白方被将军,输出
\texttt{check} ,若黑方被将军,输出\texttt{CHECK} ,若没有任何一方被将军,输出\texttt{none} 。
题目分析虽不难,但码量极大,一定要耐心的敲完!
Code
#include <bits/stdc++.h>
using namespace std;
bool at(int kr, int kc, bool iw, const vector<string>& b){ // 判断是否有一方被将军
// 判断此时国王是否受兵攻击
if(iw){
int r = kr - 1, c = kc - 1;
if(r >= 0 && c >= 0 && b[r][c]=='p') return true;
r = kr - 1, c = kc + 1;
if(r >= 0 && c < 8 && b[r][c]=='p') return true;
}
else{
int r = kr + 1, c = kc - 1;
if(r < 8 && c >= 0 && b[r][c]=='P') return true;
r = kr + 1, c = kc + 1;
if(r < 8 && c < 8 && b[r][c]=='P') return true;
}
// 判断国王此时是否受马攻击
int kn[8][2] = {{-2,-1}, {-2,1}, {-1,-2}, {-1,2},
{1,-2}, {1,2}, {2,-1}, {2,1}};
for(int i = 0; i < 8; i++){
int r = kr + kn[i][0], c = kc + kn[i][1];
if(r >= 0 && r < 8 && c >= 0 && c < 8){
char p = b[r][c];
if(iw && p=='n') return true;
if(!iw && p=='N') return true;
}
}
// 判断国王此时是否受皇后或车攻击
int ro[4][2] = {{-1,0}, {1,0}, {0,-1}, {0,1}};
for(int i = 0; i < 4; i++){
int r = kr, c = kc;
while(1){
r += ro[i][0], c += ro[i][1];
if(r < 0 || r >= 8 || c < 0 || c >= 8) break;
char p = b[r][c];
if(p != '.'){
if(iw && (p=='r' || p=='q')) return true;
if(!iw && (p=='R' || p=='Q')) return true;
break;
}
}
}
// 判断国王此时是否受皇后或象攻击
int bi[4][2] = {{-1,-1}, {-1,1}, {1,-1}, {1,1}};
for(int i = 0; i < 4; i++){
int r = kr, c = kc;
while(1){
r += bi[i][0], c += bi[i][1];
if(r < 0 || r >= 8 || c < 0 || c >= 8) break;
char p = b[r][c];
if(p != '.'){
if(iw && (p=='b' || p=='q')) return true;
if(!iw && (p=='B' || p=='Q')) return true;
break;
}
}
}
// 判断国王此时是否受另一方国王攻击
int ki[8][2] = {{-1,-1}, {-1,0}, {-1,1}, {0,-1},
{0,1}, {1,-1}, {1,0}, {1,1}};
for(int i = 0; i < 8; i++){
int r = kr + ki[i][0], c = kc + ki[i][1];
if(r >= 0 && r < 8 && c >= 0 && c < 8){
char p = b[r][c];
if(iw && p=='k') return true;
if(!iw && p=='K') return true;
}
}
return false;
}
string pr(const string &s){ // 解析 FEN 格式的棋局
string r = "";
for(int i = 0; i < s.size(); i++){
char ch = s[i];
if(isdigit(ch)){
int cnt = ch - '0';
r.append(cnt, '.');
}
else r.push_back(ch);
}
return r;
}
int main(){
int t;
cin >> t;
while(t--){
string fen;
cin >> fen;
vector<string> p;
string tk = "";
for(int i = 0; i < fen.size(); i++){
char ch = fen[i];
if(ch=='/'){
p.push_back(tk);
tk = "";
}
else tk.push_back(ch);
}
p.push_back(tk);
vector<string> b(8);
for(int i = 0; i < 8; i++){
b[i] = pr(p[i]);
if(b[i].size() < 8)
b[i].append(8 - b[i].size(), '.');
}
int wr = -1, wc = -1, br = -1, bc = -1;
for(int i = 0; i < 8; i++){
for(int j = 0; j < 8; j++){
if(b[i][j]=='K'){
wr = i;
wc = j;
}
if(b[i][j]=='k'){
br = i;
bc = j;
}
}
}
if(wr != -1 && at(wr, wc, true, b))
cout << "check" << "\n";
else if(br != -1 && at(br, bc, false, b))
cout << "CHECK" << "\n";
else
cout << "none" << "\n";
}
return 0;
}
AC 记录
珍惜生命,远离抄袭!