4-1(Xiangqi, ACM/ICPC Fuzhou 2011, UVa1589)

4-1
本人曾有两个思路恰与一位博主不谋而合,这里放上链接:
UVA1589 解题报告
思路1:对红方的每一个棋子,把他们的必杀区域(能吃掉对方的棋子的区域)都用代替,之后对黑方的帅,试着移动四个方位,如果四个方位都会碰到’’,那么红方将死对方。就是之前要检查一下红方是否会被黑方飞帅直线击杀。

思路2:与思路1相反,先移动黑方的帅,对每一个可能移动的方位,遍历所有红方的棋子,看红方棋子能否击杀黑方。如果对四个可能的移动方位,黑方都必死,那么红方将死黑方,否则,将不死。

思路1有个问题,那就是如果黑方吃掉红方一个棋子,可能会失效。

思路二有许多技巧:
1.将马的移动放入movh数组中,“将”的移动放入mov中,可以简化程序
2.炮、车、帅对对方的“将”限制原理类似,可以通过红方棋子和”将“之间的棋子数判断“将”是否被“check”,棋子数计算通过cntblk()实现

#include <iostream>
#include <iomanip>
#include<cassert>
#include <cstring>
using namespace std;
const int mov[4][2] = { 0,1,0,-1,1,0,-1,0 };
const int movh[8][2] = { -1,2,1,2,-1,-2,1,-2,2,1,2,-1,-2,1,-2,-1 };
int board[11][11], board0[11][11];
char type[8];
int cx[8], cy[8], N, hx, hy;
bool legal(int x, int y)
{
	return x >= 1 && x <= 3 && y >= 4 && y <= 6;
}
int cntblk(int x1, int y1, int x2, int y2)
{
	int cnt = 0;
	if (y1 == y2)
	{
		int add = x1 < x2 ? 1 : -1;
		for (int i = x1 + add; i != x2; i+=add) {
			if (board[i][y1])
				++cnt;
		}
	}
	else if (x1 == x2)
	{
		int add = y1 < y2 ? 1 : -1;
		for (int i = y1 + add; i != y2; i+=add) {
			if (board[x1][i])
				++cnt;
		}
	}
	else cnt = -1;
	return cnt;
}
bool check(int x,int y)
{
	for (int i = 0; i < N; ++i)
	{
		if (x != cx[i] || y != cy[i])//判断“将”是否吃了红棋
		{
			if (type[i] == 'R' || type[i] == 'G')
			{
				if (cntblk(cx[i], cy[i], x, y)==0)
					return true;
			}
			else if (type[i] == 'H')
			{
				for (int j = 0; j < 8; ++j)
				{
					if (cx[i] + movh[j][0] == x && cy[i] + movh[j][1] == y && !board[cx[i] + mov[j / 2][0]][cy[i] + mov[j / 2][1]])
						return true;
				}
			}
			else if (type[i] == 'C')
			    if (cntblk(cx[i], cy[i], x, y) == 1)return true;
			
		}
	}
	return false;
}
int main()
{
	while (cin >> N >> hx >> hy && N)
	{
		int win = 1;
		memset(board0, 0, sizeof(board0));
		for (int i = 0; i < N; ++i)
		{
			cin >> type[i] >> cx[i] >> cy[i];
			board0[cx[i]][cy[i]] = type[i];
		}
		for (int i = 0; i < 4; ++i)
		{
			int hxcrnt = hx + mov[i][0], hycrnt = hy + mov[i][1];
			if (legal(hxcrnt, hycrnt))
			{
				memcpy(board, board0, sizeof(board0));
				board[hxcrnt][hycrnt] = 0;
				if (!check(hxcrnt, hycrnt))win = 0;
			}
		}
		if (win)cout << "YES" << endl;
		else cout << "NO" << endl;
	}
}

参考资料链接

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

进击的程序

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值