白骑士的移动 (搜索)

小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把黑战车和黑主教进攻路线跑出来,vis = 1;
  • 为什么要用bfs呢,因为遇到障碍物会停下。
  • 有个小技巧就是不能转变方向
  • 然后马就无脑乱跑就可以了,最后一步反而简单
#include<bits/stdc++.h>
using namespace std;
char a[10][10];
int vis[10][10];
int tv[10][10];
int dir1[4][2] = {{0,1},{1,0},{-1,0},{0,-1}};
int dir2[4][2] = {{-1,-1},{-1,1},{1,1},{1,-1}};
struct node{
	int x, y;
	int step;
	int dir;
};
void R(int x, int y){
	memset(tv,0,sizeof(tv));
	queue<node> q;
	node nex;
	q.push({x,y,0,-1});
	vis[x][y] = 1;
	tv[x][y] = 1;
	while(!q.empty()){
		nex= q.front();
		q.pop();
		for(int i = 0; i < 4; i ++){
			if(nex.dir!=-1){
				if(nex.dir!=i)continue;
			}
			int tx = nex.x + dir1[i][0];
			int ty = nex.y + dir1[i][1];
			if(tx<0 || ty<0 || tx>=8 || tx>=8)continue;
			if(a[tx][ty]=='Q' || a[tx][ty]=='R' || a[tx][ty]=='B')
				continue;
			if(tv[tx][ty] == 1)continue;
			tv[tx][ty] = 1;
			vis[tx][ty] = 1;
			q.push({tx,ty,0,i});
		}
	}
}
void B(int x, int y){
	memset(tv,0,sizeof(tv));
	queue<node> q;
	node nex;
	q.push({x,y,0,-1});
	vis[x][y] = 1;
	tv[x][y] = 1;
	while(!q.empty()){
		nex= q.front();
		q.pop();
		for(int i = 0; i < 4; i ++){
			if(nex.dir!=-1){
				if(nex.dir!=i)continue;
			}
			int tx = nex.x + dir2[i][0];
			int ty = nex.y + dir2[i][1];
			if(tx<0 || ty<0 || tx>=8 || tx>=8)continue;
			if(a[tx][ty]=='Q' || a[tx][ty]=='R' || a[tx][ty]=='B')
				continue;
			if(tv[tx][ty] == 1)continue;
			tv[tx][ty] = 1;
			vis[tx][ty] = 1;
			q.push({tx,ty,0,i});
		}
	}
}
int dir[8][2] = {{2,1},{1,2},{-2,1},{-1,2},{2,-1},{1,-2},{-2,-1},{-1,-2}};
int bfs(int x, int y, int x1, int y1){
	vis[x][y] = 1;
	queue<node> q;
	node nex;
	q.push({x,y,0});
	while(!q.empty()){
		nex = q.front();
		q.pop();
		if(nex.x==x1 && nex.y==y1)return nex.step;
		for(int i = 0; i < 8; i ++){
			int tx = nex.x + dir[i][0];
			int ty = nex.y + dir[i][1];
			if(tx<0 || ty<0 || tx>=8 || ty>=8)continue;
			if(vis[tx][ty] == 1)continue;
			vis[tx][ty] = 1;
			q.push({tx,ty,nex.step+1});
		}
	}
	return 0;
}
int main() {
	ios::sync_with_stdio(false);
	memset(vis,0,sizeof(vis));
	for(int i = 0; i < 8; i ++){
		cin >> a[i];
	}
	int x, y, x1, y1;
	for(int i = 0; i < 8; i ++){
		for(int j = 0 ; j < 8; j ++){
			if(a[i][j] == 'K'){
				x = i;
				y = j;
			}
			if(a[i][j] == 'Q'){
				x1 = i;
				y1 = j;
			}
			if(a[i][j] == 'R')R(i, j);
			if(a[i][j] == 'B')B(i, j);
		}
	}
	int flag = bfs(x,y,x1,y1);
	if(flag == 0) cout << "Checkmate" << endl;
	else cout << flag << endl;
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值