第三十四题 UVA1589 象棋 Xiangqi 说来惭愧

PDF

题意翻译
[输入] 输入数据≤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
车 将军的时候 需要中间没有其他棋子
炮 将军的时候 需要中间有且仅有一枚棋子
吐了

求路过大神指点江山

发布了732 篇原创文章 · 获赞 31 · 访问量 17万+

猜你喜欢

转载自blog.csdn.net/qq_35776409/article/details/103955737
今日推荐