题意翻译
[输入] 输入数据≤40组,对于每组数据,第一行有三个数:第一个数代表红方棋数 N(2≤N≤7),第二三个数代表黑将的坐标 接下来N行每行一个字符两个数,代表每个红子的详细信息,字符为棋子种类车(®,马(H),炮©),数字为坐标. 输入所有棋子的位置,保证局面合法并且红方已经将军。
[输出] 对于每组输出数据,如已经将死 ,输出‘YES’,反之输出‘No’
输入输出样例
无
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
int Red_r = 10;//红将坐标 可能会稍微方便一点吧
int Red_c = 5;
#define Maxn 8
char s[Maxn],s2[Maxn];
int x[Maxn],y[Maxn],n,r,c;;
int map[11][11];
// 判断 马
inline bool inside(int rx,int ry) {
if(rx >= 1 && rx <= 3 && ry >= 4 && ry <= 6) return true;
else return false;
}
inline bool Twi_C(int rx,int rxx,int ry) {
int cnt = 0;// 炮和将 中间有且恰好仅有一枚棋子
if(rxx < rx) swap(rx,rxx);
for(int i=1; i<=n; i++)
if(s[i] != ' ' && x[i] > rx && x[i] < rxx && y[i] == ry) cnt ++;
//本来还想着 红将 做 炮中间的zi 结果红将不可能动
return cnt == 1;
}
inline bool Twi_R(int ryy,int ry,int rx) {
int cnt = 0;
if(ryy < ry) swap(ryy,ry);
for(int i=1; i<=n; i++)
if(s[i] != ' ' && x[i] == rx && y[i] > ry && y[i] < ryy) cnt++;
return cnt == 1;
}
inline bool Twi_Ma(int k,int rx,int ry) {
int mx[] = {-2, -2, +1, -1, +2, +2, +1, -1};
int my[] = {+1, -1, +2, +2, +1, -1, -2, -2};
int bx[] = {-1, -1, 0, 0, +1, +1, 0, 0};
int by[] = { 0, 0, +1, +1, 0, 0, -1, -1};
for(int i=0; i<8; i++)
if((x[k] + mx[i] == rx) && (y[k] + my[i] == ry) && (map[x[k] + bx[i]][y[k] + by[i]] == 0)) return true;
return false;// k 号马 八种跳跃方式 均踩不到 黑将
}
inline bool Twi_(int k,int rx,int ry) {
if(x[k] == rx) {// 同行
int ryy = y[k];
if(ryy < ry) swap(ryy,ry);
for(int i=1; i<=n; i++)
if(s[i] != ' ' && y[i] > ry && y[i] < ryy) return 0;
return 1;// 军 将军 需要中间没有别的棋子
}
else {// 同列
int rxx = x[k];
if(rxx < rx) swap(rxx,rx);
for(int i=1; i<=n; i++)
if(s[i] != ' ' && x[i] > rx && x[i] < rxx) return 0;
return 1;
}
}
inline bool DiTwi(int rx,int ry) {// rx ry 黑将的移动策略
if(ry == Red_c) { // 两将照面 中间无子
bool flag = 1;
for(int i=1; i<=n; i++)
if(s[i] != ' ' && y[i] == ry) flag = 0;
if(flag) return 0;
}
for(int i=1; i<=n; i++) {
//if(x[i] == rx && y[i] == ry) continue;
if(s[i] == 'R' && Twi_(i,rx,ry) ) return 0;
if(s[i] == 'C' && y[i] == ry && Twi_C(rx,x[i],y[i])) return 0;// 炮 同一列 中间有 一枚棋子
if(s[i] == 'C' && x[i] == rx && Twi_R(ry,y[i],x[i])) return 0;// 同一行上的炮
if(s[i] == 'H' && Twi_Ma(i,rx,ry)) return 0;// 该马的一种跳法 可以踩到黑将
}
return 1;//移动到rx,ry 红方没有一个棋子可以将军 则是没有将死
}
inline bool Judge() {
int dx[] = {0,0,1,-1};
int dy[] = {1,-1,0,0};
for(int i=0; i<4; i++) {
memcpy(s,s2,sizeof(s2));
int rx = dx[i] + r,ry = dy[i] + c;
if(!inside(rx, ry)) continue;
for(int j=1; j<=n; j++)
if(x[j] == rx && ry == y[j]) s[j] = ' ';// 表示被黑将的移动给吃掉了
if(DiTwi(rx, ry)) return 0;
}
return 1;// 没救了........
}
int main(int argc,char* argv[]) {
while(scanf("%d %d %d",&n,&r,&c) == 3 && n) {
memset(map,0,sizeof(map));
for(int i=1; i<=n; i++){
cin >> s2[i];
scanf("%d %d",&x[i],&y[i]);
if(s2[i] == 'G') Red_r = x[i],Red_c = y[i],s2[i] = ' ';
map[x[i]][y[i]] = 1;
}
printf("%s\n",Judge() ? "YES" : "NO");
}
return 0;
}
改这道题目 改到后半夜,实在改不下去了, 躺下之后又想起来一个bug
车 将军的时候 需要中间没有其他棋子
炮 将军的时候 需要中间有且仅有一枚棋子
吐了
求路过大神指点江山