PTA 7-68 白骑士的移动 (30分)(bfs)

小S第一次接触国际象棋。他发现国际象棋中的Knight棋子的移动方式和中国象棋中的马类似,移动方式如图所示。
在这里插入图片描述

于是小S在棋盘上随意摆上了一些棋子,其中包括一枚白骑士、一枚黑皇后、若干黑战车和若干黑主教。

小S想知道,如何能在避开黑战车和黑主教的攻击范围的前提下,花费更少的步数吃掉黑皇后。

注1:战车的攻击范围呈直线,和中国象棋的車类似;主教的攻击范围呈斜线,无障碍物情况下可无限延伸。

注2:白骑士只能吃黑皇后,不可以吃掉黑战车和黑主教。

输入格式:

输入仅包含一组样例。

一组样例包含8行(分别对应1-8行),每行包含8个字符,每个字符代表对应行对应列的棋盘格子状况。

其中’ . ‘代表格子上没有摆放任何棋子;’ K '代表格子上摆放的是白骑士; ’ Q '代表格子上摆放的是黑皇后; ’ R '代表格子上摆放的是黑战车; ’ B '代表格子上摆放的是黑主教。

注:题目保证白骑士的初始位置不在黑战车和黑主教的攻击范围内。

输出格式:

如果白骑士可以在避开黑战车和黑主教的攻击的情况下吃掉黑皇后,则输出花费步数的最小值;否则输出"Checkmate"。

输入样例1:

R.B.QB.R
........
........
........
........
........
........
.K......

输出样例1:

4

输入样例2:

....RR.Q
........
.K......
........
........
........
........
........

输出样例2:

Checkmate

解题:

这题采用bfs,第一次找到的就是最短次数,用dfs剪枝了还会超时

#include <iostream>					//7-68 白骑士的移动 (30分)
#include <algorithm>
#include <string>
#include <queue>
using namespace std;
string str[8];
bool vis[9][9];
int jump[8][2] = {{2, 1}, {2, -1}, {1, 2}, {1, -2}, {-1, 2}, {-1, -2}, {-2, -1}, {-2, 1}};
int jump1[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
int jump2[4][2] = {{1, 1}, {1, -1}, {-1, -1}, {-1, 1}};
int a1, b1;		//终点
int ans = 100;

struct node{
	int x, y, k;
};

bool RightPlace(int x, int y)
{
	if (x >= 0 && x < 8)
		if (y >= 0 && y < 8)
			return true;
	return false;
}

void MarkR(int x, int y)		//战车
{
	vis[x][y] = true;
	for (int i = 0; i < 4; i++)
		for (int j = 1; j < 8; j++)
		{
			int xt = x + j * jump1[i][0];
			int yt = y + j * jump1[i][1];
			if(RightPlace(xt, yt))
			{
				if(str[xt][yt] == '.')
					vis[xt][yt] = true;
				else
					break;
			}
		}
}

void MarkB(int x, int y)		//主教
{
	vis[x][y] = true;
	for (int i = 0; i < 4; i++)
		for (int j = 1; j < 8; j++)
		{
			int xt = x + j * jump2[i][0];
			int yt = y + j * jump2[i][1];
			if(RightPlace(xt, yt))
			{
				if(str[xt][yt] == '.')
					vis[xt][yt] = true;
				else
					break;
			}
		}
}

void dfs(int a, int b, int k)		//dfs会超时<<<<
{
	if(a == a1 && b == b1)
	{
		cout << k << endl;
		ans = min(ans, k);
		return;
	}
	for (int i = 0; i < 8; i++)
	{
		int x = a + jump[i][0];
		int y = b + jump[i][1];
		if(RightPlace(x, y) && !vis[x][y])
		{
			vis[x][y] = true;
			if(k + 1 <= ans)
				dfs(x, y, k + 1);
			vis[x][y] = false;
		}
	}
}

int bfs(int a, int b)
{
	queue<node> q;
	q.push({a, b, 0});
	while (!q.empty())
	{
		int x = q.front().x;
		int y = q.front().y;
		int k = q.front().k;
		vis[x][y] = true;
		q.pop();

		if(x == a1 && y == b1)
			return k;

		for (int i = 0; i < 8; i++)
		{
			int xt = x + jump[i][0];
			int yt = y + jump[i][1];
			if(RightPlace(xt, yt) && !vis[xt][yt])
				q.push({xt, yt, k + 1});
		}
	}
	return -1;
}

int main()
{
	int a0, b0;		//起点
	for (int i = 0; i < 8; i++)
		cin >> str[i];

	for (int i = 0; i < 8; i++)
		for (int j = 0; j < 8; j++)
		{
			if (str[i][j] == 'K')
				a0 = i, b0 = j;
			if(str[i][j] == 'Q')
				a1 = i, b1 = j;

			if(str[i][j] == 'R')
				MarkR(i, j);
			else if(str[i][j] == 'B')
				MarkB(i, j);
		}

	// vis[a0][b0] = true;
	// dfs(a0, b0, 0);
	// if(ans == 100)
	// 	cout << "Checkmate" << endl;
	// else
	// 	cout << ans << endl;

	int t = bfs(a0, b0);
	if(t > 0)
		cout << t << endl;
	else
		cout << "Checkmate" << endl;

	system("pause");
	return 0;
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值