BFS-迷宫最短路径问题

本文详细解析了一种使用广度优先搜索(BFS)算法求解迷宫最短路径的问题。首先定义了一个包含坐标和步数的note结构体,然后通过队列进行层次遍历。在遍历过程中,不断拓展新节点并更新步数,直到找到目标节点。当找到目标节点时,输出的步数即为最短路径。整个过程保证了路径的最优化,因为每次拓展都是沿着最少步数的方向进行。
摘要由CSDN通过智能技术生成

迷宫最短路径问题

完整代码如下:

#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步

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值