ACM篇:POJ 4001 -- Xiangqi

思路:


依次考虑红方车马炮帅,标记他们能攻击到的范围。


车和将都在遇到第一个棋时停止,但要注意,第一个棋所在的位置需要被标记为可攻击,因为可能被老王吃掉。
炮类似。

马无脑模拟。


以上因为题目保证被将军,所以都未考虑黑将。

之后判断黑将所能到达的位置是否处于红方攻击范围。

#include <cstdio>
#include <cstring>
#include <cctype>
const int MAXKIND = 4;
const int MAXNUM = 2;
const int MINROW = 1;
const int MAXROW = 10;
const int MINCOL = 1;
const int MAXCOL = 9;
struct Point
{
	int ro, co;
}chess[MAXKIND+2][MAXNUM+2];

bool occu[MAXROW+2][MAXCOL+2];
char board[MAXROW+2][MAXCOL+2];
int count[MAXKIND];

bool in_palace(int r, int c)
{
	if (r >= 1 && r <= 3 && c <= 6 && c >= 4) return true;
	else return false;
}

int readchar()
{
	int t;
	while (t = getchar())
	{
		if (isalpha(t)) break;
	}
	return t;
}

int to_num(char t)
{
	switch(t)
	{
		case 'G':
			return 0;
		case 'R':
			return 1;
		case 'H':
			return 2;
		case 'C':
			return 3;
	}
}

void go_general()
{
	int cnt = 0;
	int r, c;
	while ((r = chess[0][cnt].ro) && (c = chess[0][cnt].co ))
	{
		cnt++;
		for (int i = r - 1; i >= MINROW && (board[i+1][c] == 'G' || !board[i+1][c]); i--)
		{
			occu[i][c] = true;
		}
	}
}

void go_chariot()
{
	int cnt = 0;
	int r, c;
	while ((r = chess[1][cnt].ro) && (c = chess[1][cnt].co))
	{
		cnt++;
		for (int i = r-1; i >= MINROW && (board[i+1][c] == 'R' || !board[i+1][c]); i--)
		{
			occu[i][c] = true;
		}
		for (int i = r+1; i <= MAXROW && (board[i-1][c] == 'R' || !board[i-1][c]); i++)
		{
			occu[i][c] = true;
		}
		for (int j = c-1; j >= MINCOL && (board[r][j+1] == 'R' || !board[r][j+1]); j--)
		{
			occu[r][j] = true;
		}
		for (int j = c+1; j <= MAXCOL && (board[r][j-1] == 'R' || !board[r][j-1]); j++)
		{
			occu[r][j] = true;
		}
	}
}

void go_horse()
{
	int cnt = 0;
	int r, c; 
	while ((r = chess[2][cnt].ro ) && (c = chess[2][cnt].co))
	{
		cnt++;
		if (!board[r][c+1])
		{
			if (in_palace(r-1, c+2)) occu[r-1][c+2] = true;
			if (in_palace(r+1, c+2)) occu[r+1][c+2] = true;
		}
		if (!board[r+1][c])
		{
			if (in_palace(r+2, c-1)) occu[r+2][c-1] = true;
			if (in_palace(r+2, c+1)) occu[r+2][c+1] = true;
		}
		if (!board[r][c-1])
		{
			if (in_palace(r-1, c-2)) occu[r-1][c-2] = true;
			if (in_palace(r+1, c-2)) occu[r+1][c-2] = true;
		}
		if (!board[r-1][c])
		{
			if (in_palace(r-2, c-1)) occu[r-2][c-1] = true;
			if (in_palace(r-2, c+1)) occu[r-2][c+1] = true;
		}
	}
}

void go_cannon()
{
	int cnt = 0;
	int r, c;
	int mark = 0;
	while ((r = chess[3][cnt].ro) && (c = chess[3][cnt].co))
	{
		cnt++;
		mark = 0;
		for (int i = r-1; i >= MINROW; i--)
		{
			if (mark) occu[i][c] = true;
			if (board[i][c] && ++mark == 2) break; 
		}
		mark = 0;
		for (int i = r+1; i <= MAXROW; i++)
		{
			if (mark) occu[i][c] = true;
			if (board[i][c] && ++mark == 2) break;
		}
		mark = 0;
		for (int j = c-1; j >= MINCOL; j--)
		{
			if (mark) occu[r][j] = true;
			if (board[r][j] && ++mark == 2) break;
		}
		mark = 0;
		for (int j = c+1; j <= MAXCOL; j++)
		{
			if (mark) occu[r][j] = true;
			if (board[r][j] && ++mark == 2) break;
		}
	}
}

int ROW[] = {0, 0, 1, -1};
int COL[] = {1, -1, 0, 0};
bool if_live(int r, int c)
{
	for (int i = 0; i < 4; i++)
	{
		if (in_palace(r+ROW[i], c+COL[i]) && !occu[r+ROW[i]][c+COL[i]])
			return true;
	}
	return false;
}
int main()
{
	int n;
	int x, y;
	while (scanf("%d%d%d", &n, &x, &y) && n && x && y)
	{
		// init
		memset(chess, 0, sizeof(chess));
		memset(count, 0, sizeof(count));
		memset(board, 0, sizeof(board));
		memset(occu, 0, sizeof(occu));
		
		//input
		for (int i = 1; i <= n; i++)
		{
			char t;
			int tr, tc;
			int tnum;
			
			t = readchar();
			scanf("%d%d", &tr, &tc);
			board[tr][tc] = t;
			tnum = to_num(t);
			chess[tnum][count[tnum]].ro = tr;
			chess[tnum][count[tnum]++].co = tc;
		}	
		//work
		go_general();
		go_chariot();
		go_horse();
		go_cannon();
		//print
		printf("%s\n", (if_live(x, y)) ? "NO" : "YES");
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值