bfs 求解迷宫最短路径问题

问题描述

下图给出了一个迷宫的平面图,其中标记为 1 的为障碍,标记为 0 的为可以通行的地方。
010000
000100
001001
110000

迷宫的入口为左上角,出口为右下角,在迷宫中,只能从一个位置走到这 个它的上、下、左、右四个方向之一。对于上面的迷宫,从入口开始,可以按DRRURRDDDR 的顺序通过迷宫, 一共 10 步。其中 D、U、L、R 分别表示向下、向上、向左、向右走。

对于下面这个更复杂的迷宫(30 行 50 列),请找出一种通过迷宫的方式, 其使用的步数最少,在步数最少的前提下,请找出字典序最小的一个作为答案。 请注意在字典序中D<L<R<U。
(题源:蓝桥杯2019省赛)

题目分析
迷宫问题有两种问法:
1.求所有能够从起点到终点的路径     采用dfs+回溯法
2.求最短路径   采用bfs

dfs与bfs的不同点:
1.dfs是一种“一往无前,不撞南墙不回头”的搜索方法,因此它每次搜索成功的路径的长度是不确定的,即不一定是最短路径。
2.而bfs是一种“道生一,一生二,二生三,三生万物”似的搜索方式,就像火影鸣人的分身一样,一圈一圈地向外扩展,
因此它寻找到的路径一定是最短路径。

具体bfs实现思路为

用数据结构队列来存储每一个点,因为要求在最短的前提下字典序还要最小,所以要对探索的顺序进行一个排序
即 上 左 右 下 (D,L,R,U),用一个数组pre来存储每一个点是通过哪种操作到达的,同时还要有一个visit数组来
记录某点是否已经访问过了。
参考code
#include<bits/stdc++.h>
using namespace std;
					
int maze[50][50],visit[50][50] , pre[50][50];
struct node{
	int x,y;     //结构体,表示节点的横纵坐标
};
int dx[4] = {1,0,0,-1},dy[4] = {0,-1,1,0};  //代表四个方向 
int  n,m;//代表行与列 
char ch[4] = {'D','L','R','U'};	 //D 向下,U向上,L向左,R向右 
queue<node>qu;  //队列 
void bfs( )
{	
	node start;
	start.x = 1;start.y=1;      //默认迷宫的出发点为(1,1)
	qu.push(start);        //入队列
	visit[1][1] = 1;      //第一个点已经访问过了
	while(!qu.empty())          // 如果队列不空
	{
		node now = qu.front();    //队头元素,并出队
		qu.pop();
		for(int i=0;i<4;i++)   //遍历四个方向,注意按顺序来
		{
			int xx = now.x+dx[i],yy = now.y+dy[i];     //记录下一个节点
			node next; 
			next.x = xx;
			next.y = yy;               //注意边界条件,迷宫墙壁,是否已经访问过
			if(xx<1||xx>n||yy<1||yy>m||maze[xx][yy]||visit[xx][yy]) continue;
		
			pre[xx][yy] = i;      //记录该节点的前驱,即通过哪种方式到达该点的
			visit[xx][yy] = 1;       // 记录已经遍历过了
			qu.push(next);        // 入队列
		}
	}
}
int main()
{
	n = 30; 
	m = 50;
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
			{
			char a;
			cin>>a;
			maze[i][j]=a-'0';
			}
	bfs(); 
	
	char ans[200];
	int num = 0;

	while(n!=1 || m!=1)
	{           // 倒序存储下来,从终点开始计算
		int i = pre[n][m];
		ans[num++] = ch[i];
		n -=dx[i];
		m -=dy[i];
	}
	for(int i=num-1;i>=0;i--)
		cout<<ans[i];
}

最后结果为DDDDRRURRRRRRDRRRRDDDLDDRDDDDDDDDDDDDRDDRRRURRUURRDDDDRDRRRRRRDRRURRDDDRRRRUURUUUUUUULULLUUUURRRRUULLLUUUULLUUULUURRURRURURRRDDRRRRRDDRRDDLLLDDRRDDRDDLDDDLLDDLLLDLDDDLDDRRRRRRRRRDDDDDDRR

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值