uva1589 Xiangqi

自己写的

//uva1589 Xiangqi
//@@使用scanf就是过不了,用cin就过了

#include<iostream>
#include<string.h>
using namespace std;
int cnt = 0;
int rnum;
int br, bc;
int gen = 0;
//i是传入的这个棋子在第几个
/*@@这个将军函数错了。
1.蓝棋先行,所以如果已经对面了的话将直接赢。
2.就算这一列有红棋,也可能飞将
所以将general和charoit函数合并了*/
/*void general(int i, char type, int pos[][2+3], int brd[][9 + 3]) {
	
	for (int j = 1; j <= rnum; j++) {
		if (j != i) {
			if (pos[j][2] == pos[i][2]) {
				return;
			}
		}
	}
	brd[1][pos[i][2]] = 1;
	brd[2][pos[i][2]] = 1;
	brd[3][pos[i][2]] = 1;
	if (bc == pos[i][2])
		gen = 1;
	return;
}*/
void charoit(int i, char type, int pos[][2 + 3], int brd[][9 + 3]) {
	int up =1, down =10, left =1, right = 9;//看看车最多能够走到哪里
	for (int j = 1; j <= rnum; j++) {
		if (j != i) {
			if (pos[i][1]==pos[j][1]) {//同一行
				if (pos[j][2] >= left&&pos[j][2]<pos[i][2]) {
					left = pos[j][2];
				}
				if (pos[j][2] <= right && pos[j][2]>=pos[i][2]) {
					right = pos[j][2];
				}
			}
			if (pos[i][2] == pos[j][2]) {//同一列
				if (pos[j][1] >= up && pos[j][1] <= pos[i][1]) {
					up = pos[j][1];
				}
				if (pos[j][1] <= down && pos[j][1] >= pos[i][1]) {
					down = pos[j][1];
				}
			}
		}
	}

	for (int j = up; j <= down; j++) {
		//printf("fuvk");
		if(j!=pos[i][1])/*@@考虑到将可能会吧红色的棋子吃掉,所以棋子本身所在的位置不能够动。*/
			brd[j][pos[i][2]] = 1;
	}
	for (int j = left; j <= right; j++) {
		if(j!=pos[i][2])
			brd[pos[i][1]][j] = 1;
	}
	if (type=='G'&&bc==pos[i][2]&&up<=br) {
		gen = 1;
	}
}
void cannon(int i, char type, int pos[][2 + 3], int brd[][9 + 3]) {
	int up = 1, down = 10, left = 1, right = 9;//看看车最多能够走到哪里
	int up1 = 1, down1 = 10, left1 =1, right1 = 9;
	//先找最近的
	for (int j = 1; j <= rnum; j++) {
		if (j != i) {
			if (pos[i][1] == pos[j][1]) {//同一行
				if (pos[j][2] >= left && pos[j][2] <= pos[i][2]) {
					left = pos[j][2];
				}
				if (pos[j][2] <= right && pos[j][2] >= pos[i][2]) {
					right = pos[j][2];
				}
			}
			if (pos[i][2] == pos[j][2]) {//同一列
				if (pos[j][1] >= up && pos[j][1] <= pos[i][1]) {
					up = pos[j][1];
				}
				if (pos[j][1] <= down && pos[j][1] >= pos[i][1]) {
					down = pos[j][1];
				}
			}
		}
	}
	//再找第二近的
	for (int j = 1; j <= rnum; j++) {
		if (j != i) {
			if (pos[i][1] == pos[j][1]) {//同一行
				/*@@先把全部的变量之间的关系想清楚了在来行动。*/
				//left1  pos[j] left pos[i] right posj right1
				if (pos[j][2] < left&&pos[j][2]>=left1 && pos[j][2] <= pos[i][2]) {
					left1 = pos[j][2];
				}
				if (pos[j][2] > right && pos[j][2] <= right1 && pos[j][2] >= pos[i][2]) {
					right1 = pos[j][2];
				}
			}
			if (pos[i][2] == pos[j][2]) {//同一列
				//up1  pos[j] up pos[i] down posj down1
				if (up1<=pos[j][1]&&pos[j][1]<up&&pos[j][1]<=pos[i][1]) {
					up1 = pos[j][1];
				}
				if (down1>=pos[j][1]&&pos[j][1]>down&&pos[j][1]>=pos[i][1]) {
					down1 = pos[j][1];
				}
			}
		}
	}
	/*@@关于炮能够打击的范围需要谨慎思考。首先确定边界,在思考边界能不能够取得到*/
	for (int j = up1; j < up; j++) {
		brd[j][pos[i][2]] = 1;
	}
	for (int j = down + 1; j <= down1; j++) {
		brd[j][pos[i][2]] = 1;
	}
	for (int j = left1; j < left; j++) {
		brd[pos[i][1]][j] = 1;
	}
	for (int j = right + 1; j <= right1; j++) {
		brd[pos[i][1]][j] = 1;
	}
}
void horse(int i, char type, int pos[][2 + 3], int brd[][9 + 3]) {
	int up = 1, down = 1, right = 1, left = 1;

	for (int j = 1; j <= rnum; j++) {
		if (i != j) {
			if (pos[i][1] == pos[j][1]) {
				if (pos[i][2] - 1 == pos[j][2]) {
					left = 0;
				}
				else if (pos[i][2] + 1 == pos[j][2]) {
					right = 0;
				}
			}
			if (pos[i][2] == pos[j][2]) {
				if (pos[i][1] - 1 == pos[j][1]) {
					up = 0;
				}
				else if (pos[i][1] + 1 == pos[j][1]) {
					down = 0;
				}
			}
		}
	}
	if (up == 1) {
		if (pos[i][1] >= 2) {
			brd[pos[i][1] - 2][pos[i][2] - 1] = 1;
			brd[pos[i][1] - 2][pos[i][2] + 1] = 1;
		}
		
	}
	if (down == 1) {
		brd[pos[i][1] + 2][pos[i][2] - 1] = 1;
		brd[pos[i][1] + 2][pos[i][2] + 1] = 1;
	}
	if (left == 1) {
		if (pos[i][2] >= 2) {
			brd[pos[i][1] + 1][pos[i][2] - 2] = 1;
			brd[pos[i][1] - 1][pos[i][2] - 2] = 1;
		}
	}
	if (right == 1) {
		brd[pos[i][1] + 1][pos[i][2] + 2] = 1;
		brd[pos[i][1] - 1][pos[i][2] + 2] = 1;
	}
}
//分配
void redeat(int i, char type, int pos[][2 + 3], int brd[][9 + 3]) {
	//brd[pos[i][1]][pos[i][2]] = 1;
	if (type == 'G') {
		charoit(i, type, pos, brd);
	}
	else if (type == 'R') {
		charoit(i, type, pos, brd);
	}
	else if (type == 'C') {
		cannon(i, type, pos, brd);
	}
	else if (type == 'H') {
		horse(i, type, pos, brd);
	}
}
//判断黑骑
int canbgo(int x, int y, int brd[][9 + 3]) {//0是可以走,1是不能够走
	if (gen == 1) {
		gen = 0;//@@使用完了之后记得归零
		return 0;
	}
		
	if ((!(4<=y&&y<=6&&1<=x&&x<=3))) {//不在palace
		return 1;
	}
	return brd[x][y];
}
int main() {
	//freopen("in.txt", "r", stdin);
	//freopen("out.txt", "w", stdout);
	int brd[10+3][9+3];
	char type[7 + 3];//红旗的类型
	int pos[7 + 3][2 + 3];//红旗的坐标
	while (cin>>rnum>>br>>bc, rnum != 0 && br != 0 && bc != 0) {
		memset(brd,0,sizeof(brd));
		memset(type, 0, sizeof(type));
		memset(pos, 0, sizeof(pos));
		
		cnt++;
	//	printf("%d\n", cnt);
		for (int i=1; i<=rnum;i++) {//读入红旗
		//	while(getchar()=='\n'){}
			getchar();
			cin >> type[i];
			cin >> pos[i][1] >> pos[i][2];
		}
		for (int i = 1; i <= rnum; i++) {
			redeat(i,type[i],pos,brd);
		}

		if (canbgo(br - 1, bc,brd) == 0 || canbgo(br + 1,bc,brd) == 0 || 
			canbgo(br, bc-1, brd) == 0 || canbgo(br, bc+1, brd) == 0) {//up down left right
			printf("NO");//@@NO 还是No!!
		}
		else {
			printf("YES");
		}
		printf("\n");
		/*
		for (int q = 1; q <= 10; q++) {
			for (int w = 1; w <= 9; w++) {
				printf("%d ", brd[q][w]);
			}
			printf("\n");
		}
		*/
	}
	return 0;
}


//学习了@wyjoutstanding的方法后模仿写一个
/*他的方法和我的最大的不同就是:我用brd储存“有危险的位置”,他用brd储存“有棋子的位置”*/
#include<stdio.h>
#include<string.h>
#include<iostream>

#define R 10
#define C 9
using namespace std;

char type[7 + 3];
int pos[7 + 3][2 + 1];
int brd[10 + 3][9 + 3];
int gogen[][4] = {{-1,0},{1,0},{0,-1},{0,1} };//up,down.left.right
int gohorse[][4] = {{-2,-1},{-2,1},{2,-1},{2,1},{-1,-2},{1,-2},{-1,2},{1,2} };
int br, bc;
int min(int x, int y) {
	return x > y ? y : x;
}
int max(int x, int y){
	return x > y ? x : y;
}
int horbetw(int x, int y, int ty) {
	int cnt = 0;
	int up = min(y,ty), down = max(y,ty);
	for (int i = up; i <= down; i++) {
		if (brd[x][i])
			cnt++;
	}
	cnt--;
	cnt -= brd[x][y];
	return cnt;
}
int verbetw(int x, int y, int tx) {
	int cnt = 0;
	int up = min(x, tx),down=max(x,tx);
	for (int i = up; i <= down; i++) {
		if (brd[i][y])
			cnt++;
	}
	cnt --;
	cnt -= brd[x][y];
	return cnt;
}
int inbrd(int x, int y, bool isgen) {//isgen==1则是帅,否则是车马炮
	if (isgen) {
		if (1 <= x && x <= 3 && 4 <= y && y <= 6) {
			return 1;
		}
	}
	else {
		if (1 <= x && x <= 10 && 1 <= y && y <= 9) {
			return 1;
		}
	}
	return 0;
}
int redeat(int i,int tx,int ty) {
	if (type[i]=='G'&&pos[i][2]==ty&&verbetw(tx,ty,pos[i][1])==0) {
		return 1;
	}
	if (type[i] == 'R' && //车
		(pos[i][2] == ty && verbetw(tx, ty, pos[i][1]) == 0 ||
		 pos[i][1] == tx && horbetw(tx, ty, pos[i][2]) == 0)) {
		return 1;
	}

	if (type[i] == 'C' && //炮
		(pos[i][2] == ty && verbetw(tx, ty, pos[i][1]) == 1 ||
		 pos[i][1] == tx && horbetw(tx, ty, pos[i][2]) == 1)) {
		return 1;
	}
	if (type[i] == 'H') {
		for (int j = 0; j < 8; j++) {
			int hfootx = pos[i][1] + gogen[j / 2][0], hfooty = pos[i][2] + gogen[j / 2][1];
			int hx = pos[i][1] + gohorse[j][0], hy = pos[i][2] + gohorse[j][1];

			if (brd[hfootx][hfooty]==0 && hx==tx&&hy==ty&& inbrd(hx, hy, 0) ) {//不蹩脚&&不出界&&吃到
				return 1;
			}
		}
	}
	return 0;
}

int main() {
//	freopen("in.txt", "r", stdin);
//	freopen("out.txt", "w", stdout);
	int rnum,ischeck=0;
	while (cin >> rnum >> br >> bc, !(rnum == 0 && br == 0 && bc == 0)) {
		memset(brd, 0, sizeof(brd));
		memset(type, 0, sizeof(type));
		memset(pos, 0, sizeof(pos));

		for (int i = 1; i <= rnum; i++) {//读入
			cin >> type[i] >> pos[i][1] >> pos[i][2];
			brd[pos[i][1]][pos[i][2]] = 1;
		}

		for (int i = 0; i < 4; i++) {//将分别向上下左右四步走
			
			int tx, ty;
			tx = br + gogen[i][0];
			ty = bc + gogen[i][1];
			if (inbrd(tx, ty, 1)) {
				ischeck = 0;
				for (int j = 1; j <= rnum; j++) {
					if (redeat(j, tx, ty)) {//j号棋子可以把这样移动后的将吃掉
						ischeck = 1;
						break;
					}
				}
				if (ischeck == 0) {//这种走法无法被任何一个红色的棋子吃掉---NO被将军
					break;
				}
			}
		}
		printf("%s\n", ischeck == 0 ? "NO" : "YES");
	}

	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值