下象棋

本文介绍了一个基于象棋中马的行走规则的迷宫问题。通过使用广度优先搜索算法(BFS),解决了一个二维矩阵迷宫中,避开障碍物从起点到达终点所需的最少步数问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

江湖是什么,对于在象棋界厮杀的QQ来说,江湖就是一个矩阵,他的目标,就是在江湖之中骑着马,从他的位置出发,走到终点。

当然,QQ的马也遵从中国象棋中的“马走日”的规则,而且在矩阵中,也会有一些障碍物,马不能跳到障碍物上;如果大钉的马面前有障碍物,即被“别马腿”,那么他将不能跳向有障碍物的左前和右前这两个方向。

请问最少需要多少步,大钉才能骑着马跳到终点。

有多组测试样例。

每组第一行有两个数 n 和 m,代表矩阵的行数和列数,2 <= n <= m < 100。

接下来输入 n 行的字符串,其中 's' 代表起点,'e' 代表终点,'.'代表空地,'#'代表障碍物。

对应每组输入,输出骑马跳到终点的最小步数,如果跳不到终点,输出 -1。

 复制
3 3
s..
...
..e

3 3
s#.
...
#.e
4
-1
首先确认下能用bfs做后就比较容易写了,比较麻烦的是剪枝。

如何依次试探当前棋子可达的八个位置,还要不能被“别马腿”。
#include<iostream>
#include<string.h>
#include<math.h>
#include<queue>
#define M 105
using namespace std;
char map[M][M];
int vis[M][M];
int dir[8][2] = {{1,2},{1,-2},{-1,2},{-1,-2},{2,1},{2,-1},{-2,1},{-2,-1}};
int n,m,sx,sy,ex,ey,min,ans;

struct node{
	int x,y,step;
};
int check(int x,int y)
{
	if(x<0||x>=n||y<0||y>=m)
	return 1;
	if(vis[x][y]||map[x][y]=='#')
	return 1;
	return 0;
}

int bfs()
{
	
	queue<node> Q;
	node now,next;
	now.x = sx;
	now.y = sy;
	now.step = 0;
	vis[now.x][now.y] = 1;
	Q.push(now);

	ans = 0;
	
	while(!Q.empty())
	{
		now = Q.front();
		Q.pop();
	
		if(map[now.x][now.y]=='e' )
		{
		ans = 1; 
		return now.step;
		} 

		
		for(int i = 0; i < 8;i++)
		{
			next = now;
			
			
		//优化后的写法,可能做得多了后能一眼看出来吧..	
		//	if(map[now.x+dir[i][0]/2][now.y+dir[i][1]/2]=='#')
		//	continue;
			
		//想当然的,错误的写法	
		//	if(abs(dir[i][0])==1&&map[now.x][now.y+dir[i][0]]=='#')
		//	continue; 
		//	if(abs(dir[i][1])==1&&map[now.x+dir[i][1]][now.y]=='#')	
		//	continue; 
		
		//有点啰嗦但正确的写法	
			if((i==0)&&(map[now.x][now.y+1]=='#'))
			continue;
			if((i==1)&&(map[now.x][now.y-1]=='#'))
			continue;
			if((i==2)&&(map[now.x][now.y+1]=='#'))
			continue;
			if((i==3)&&(map[now.x][now.y-1]=='#'))
			continue;
			if((i==4)&&(map[now.x+1][now.y]=='#'))
			continue;
			if((i==5)&&(map[now.x+1][now.y]=='#'))
			continue;
			if((i==6)&&(map[now.x-1][now.y]=='#'))
			continue;
			if((i==7)&&(map[now.x-1][now.y]=='#'))
			continue;
				
			next.x+=dir[i][0]; 
			next.y+=dir[i][1];
			if(check(next.x,next.y))
				continue;
			 
			next.step = now.step+1;
			Q.push(next);
			vis[next.x][next.y] = 1;		
		}	
		
	}
	if(!ans)
	return -1;
	
	
	
	
}

int main()
{
	freopen("chess.txt","r",stdin);
	while(cin>>n>>m)
	{
		
		memset(vis,0,sizeof(vis));
		memset(map,'\0',sizeof(map));
		for(int i = 0; i < n;i++)
		scanf("%s",&map[i]);
		
		for(int i = 0; i < n;i++)
			for(int j = 0;j < m;j++)
			if(map[i][j]=='s')
			{
				sx = i;sy = j;	
				cout<<bfs()<<endl;
			}
		
		
	}
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值