BFS-迷宫最短路径问题

Posted 桃花涣小鱼干

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BFS-迷宫最短路径问题相关的知识,希望对你有一定的参考价值。

迷宫最短路径问题

完整代码如下:

#include<stdio.h>
struct note
{
	int x;//横坐标
	int y;//纵坐标
	int s;//步数
};
int main()
{
	struct note que[2501];
	int a[51][51] = { 0 }, book[51][51] = { 0 };
	int next[4][2] = { {0,1} ,{1,0} ,{0,-1}, {-1,0} };
	int head, tail;//引入队列
	int i, j, k, m, n, startx, starty, p, q, tx, ty, flag;
	//读入目标迷宫大小
	scanf("%d %d", &n, &m);
	//读入迷宫
	for (i = 1; i <= n; i++)
		for (j = 1; j <= m; j++)
			scanf("%d", &a[i][j]);
	//读入起点和终点
	scanf("%d %d %d %d", &startx, &starty, &p, &q);
	//队列初始化
	head = 0;
	tail = 1;
	//起点入队
	que[1].x = startx;
	que[1].y = starty;
	que[1].s = 0;
	//标记起点
	book[startx][starty] = 1;
	flag = 0;//标识符
	while (head < tail)
	{
		head++;
		for (k = 0; k <= 3; k++)
		{
			//父单元按规律向4个方向拓展
			tx = que[head].x + next[k][0];
			ty = que[head].y + next[k][1];
			if (tx<1 || tx>n || ty<1 || ty>m)
				continue;//越界则重新试探
			if (a[tx][ty] == 0 && book[tx][ty] == 0)
			{
				//拓展成功则标记拓展的点并将其入队,累加步数。
				tail++;
				book[tx][ty] = 1;
				que[tail].x = tx;
				que[tail].y = ty;
				que[tail].s = que[head].s + 1;
			}
			//拓展到目标点时结束拓展调用标识符结束拓展
			if (tx == p && ty == q)
			{
				flag = 1;
				break;
			}
		}
		//若成功标记则结束while循环
		if (flag == 1)
			break;
	}
	printf("%d", que[tail].s);
	getchar();
	getchar();
	return 0;
}

思路详解

第一步:定义note结构体

我们要记录最路径,路径大小和经过的点数有关
顾名思义我们需要在点上做文章
一个点拥有(x,y)坐标
我们定义一个含距离的关于点的结构体
如下:

struct note
{
	int x;//横坐标
	int y;//纵坐标
	int s;//步数
};

点的个数和迷宫大小有关
这里我们取最大值如下:

struct note que[2501];

第二步:引入队列的思维

BFS搜索🔍是由父层向下遍历探索所有可能的子结构
探索成功后之前的子层成为了新的父层继续上述操作
不由可以联想到
父到子 >> head向下试探,成功则 tail++
子成父 >> head++
如下:

while (head < tail)
	{
		head++//将1单元成为父单元
		for (k = 0; k <= 3; k++)
		{
			//父单元按规律向4个方向拓展
			tx = que[head].x + next[k][0];
			ty = que[head].y + next[k][1];
			if (tx<1 || tx>n || ty<1 || ty>m)
				continue;//越界则重新试探
			if (a[tx][ty] == 0 && book[tx][ty] == 0)
			{
				//拓展成功则标记拓展的点并将其入队,累加步数。
				tail++;//扩充队列,将新的点入队
				book[tx][ty] = 1;
				que[tail].x = tx;
				que[tail].y = ty;
				que[tail].s = que[head].s + 1;
			}
			//拓展到目标点时结束拓展调用标识符结束拓展
			if (tx == p && ty == q)
			{
				flag = 1;
				break;
			}
		}
		//若成功标记则结束while循环
		if (flag == 1)
			break;
	}

第三步:最小路径

问题1:为什么拓展到终点时必为最短路径?
解答:因为每一层拓展均为步数加1,所以拓展的过程中步数是一样累加的
并没有多走的情况,同步出发,并且只要到终点后while循环便会停止,所得> 一定为最短路径

问题2:输出最短路径时为什么要用 que[tail].s ?
解答:我们刚开始定义tail为1,tail表示队尾位置,成功拓展至终点后 ,终点即为队尾位置即que[tail].s;


summary:

1)本题和BFS-马的遍历异同之处?

本题:将距离s定义在结构体之内,使得每一个节点均含有到此的最小步数
other:马的遍历是将距离放在一个二维数组里面,二维数组的下标为位置坐标,我们需要关注的是起点位置为队列的首位,符合以下对应关系:
坐标:(sx,sy)>>(qun[1].x,qun[1].y)即队列第一单元
步数:a[sx][sy]=0>>a[qun[1].x][qun[1].y]=0即队列第一单元对应0步

以上是关于BFS-迷宫最短路径问题的主要内容,如果未能解决你的问题,请参考以下文章

[bfs最短路] aw1076. 迷宫问题(bfs最短路+模板题)

迷宫的最短路径 (BFS)

BFS求解迷宫的最短路径问题

迷宫的最短路径问题(BFS)

bfs_迷宫求最短路径

迷宫的最短路径(简单BFS)