BFS专题4 迷宫最短路径(输出路径)

本文介绍了使用广度优先搜索(BFS)方法在给定迷宫地图中寻找从起点到终点的路径,通过记录每个点的前一个最优位置实现路径追踪。

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

题目:样例:

输入
3 3
0 1 0
0 0 0
0 1 0

输出
1 1
2 1
2 2
2 3
3 3

思路:

        这里刚开始看的时候会可能有点复杂了,因为是递归。

但是只要理解了含义,脑袋里模拟一下还是可以理解的。首先还是 之前那样 BFS 常规搜索

只是这里不用输出步数了,所以我们可以省略一层循环,直接搜索求路径。

求路径的方法核心思想就是 记录每个点是由哪上一个点所得来的。

然后记录完全部的点所对应的上一个点后,从终点递归一遍到起点,然后输出路径即可。

代码详解如下:

#include <iostream>
#include <queue>
#include <cstring>
#define endl '\n'
#define x first
#define y second
#define mk make_pair
#pragma GCC optimize(3,"Ofast","inline")
#define ___G std::ios::sync_with_stdio(false),cin.tie(0), cout.tie(0)
using namespace std;
const int N = 300;

using PII = pair<int, int>;

// 控制走动方向
int dx[4] = {1, 0, -1, 0};
int dy[4] = {0, 1, 0, -1};

int n, m;	// 迷宫大小
int r[N][N];	// 记录走动过的地方
int g[N][N];	// 迷宫地图

PII pre[N][N];	// 记录路径

// 走动下一个坐标条件
inline bool isRun(int x, int y)
{
	return (x >= 0 && x < n && y >= 0 && y < m && !r[x][y] && !g[x][y]);
}


inline bool BFS(int x, int y)
{
	// 存储坐标
	queue<PII>q;
	// 存储起点
	q.push(mk(x, y));

	// 开始广度搜索
	while (q.size())
	{
		auto now = q.front();
		q.pop();

		if (now.x == n - 1 && now.y == m - 1)
		{
			// 如果已经走动到了右下角的出口
			// 结束搜索
			return false;
		}

		// 标记已经走动过了当前的地点
		r[now.x][now.y] = true;

		// 枚举四个方向能否走动
		for (int i = 0; i < 4; ++i)
		{
			// 取出该方向的坐标
			int bx = now.x + dx[i];
			int by = now.y + dy[i];

			// 判断是否满足走动条件
			if (isRun(bx, by))
			{
				// 存储下一次走动的坐标
				q.push(mk(bx, by));

				// 标记下一次会走动的坐标
				r[bx][by] = true;

				// 记录路径
				// 下一个点是 由 哪上一个最优的点得到的
				// 然后 反过来递归回去找 就得到 起点到终点的路径了
				pre[bx][by] = mk(now.x, now.y);
			}
		}
	}
	// 如果不能走到终点输出结果
	return true;
}

inline void Print_path(PII now)
{
	// 取出当前 now 对应的上一个的坐标
	auto previous = pre[now.x][now.y];

	// 如果递归到达了边界,说明已经到达了起点
	// 开始输出路径
	if (previous == PII(-1, -1))
	{
		cout << now.x + 1 << ' ' << now.y + 1 << endl;
		return ;
	}

	// 继续递归往回找路径
	Print_path(previous);

	cout << now.x + 1 << ' ' << now.y + 1 << endl;
	return ;
}
inline void solve()
{
	// 这里是初始化路径全部为 -1,-1,作为递归边界
	memset(pre, -1, sizeof pre);

	cin >> n >> m;
	for (int i = 0; i < n; ++i)
	{
		for (int j = 0; j < m; ++j)
		{
			cin >> g[i][j];
		}
	}
	if (BFS(0, 0))
	{
		puts("-1");
	}
	else
	{
		// 打印路径
		// 由于是从后面开始记录上一个路径点
		// 所以我们应该从终点开始递归查找路径
		Print_path(mk(n - 1, m - 1));
	}
}


int main()
{
//	freopen("a.txt", "r", stdin);
	___G;
	int _t = 1;
//	cin >> _t;
	while (_t--)
	{
		solve();
	}

	return 0;
}

最后提交:

### BFS算法实现迷宫问题的最短路径 BFS(广度优先搜索)是一种逐层扩展的搜索策略,其核心在于利用队列来存储待访问节点的信息。对于迷宫问题中的最短路径求解,BFS能够保证首次抵达目标节点时所经过的路径是最短的[^1]。 以下是基于Python语言的一个典型实现: #### 输入定义 假设迷宫是一个二维数组 `maze`,其中: - `0` 表示可以通过的位置; - `1` 表示墙壁或不可通过的位置; - 起点坐标为 `(start_x, start_y)`; - 终点坐标为 `(end_x, end_y)`。 #### 输出定义 返回从起点到终点的最短路径长度。如果没有可行路径,则返回 `-1`。 ```python from collections import deque def bfs_shortest_path(maze, start_x, start_y, end_x, end_y): rows, cols = len(maze), len(maze[0]) # 如果起始点或结束点超出边界或者被墙挡住,直接返回 -1 if maze[start_x][start_y] != 0 or maze[end_x][end_y] != 0: return -1 visited = [[False for _ in range(cols)] for _ in range(rows)] queue = deque() directions = [(0, 1), (1, 0), (0, -1), (-1, 0)] # 右、下、左、上四个方向移动向量 # 将起点入队并标记已访问 queue.append((start_x, start_y, 0)) # 记录当前坐标和步数 visited[start_x][start_y] = True while queue: current_x, current_y, steps = queue.popleft() # 出队 # 判断是否到达终点 if current_x == end_x and current_y == end_y: return steps # 探索四个方向上的相邻格子 for dx, dy in directions: next_x, next_y = current_x + dx, current_y + dy # 检查新位置是否合法且未访问过 if 0 <= next_x < rows and 0 <= next_y < cols and not visited[next_x][next_y] and maze[next_x][next_y] == 0: queue.append((next_x, next_y, steps + 1)) visited[next_x][next_y] = True # 若遍历结束后仍未找到终点,说明不存在路径 return -1 ``` #### 测试案例 以下是对上述函数的一次测试调用: ```python if __name__ == "__main__": maze = [ [0, 1, 0, 0, 0], [0, 1, 0, 1, 0], [0, 0, 0, 1, 0], [0, 1, 1, 1, 0], [0, 0, 0, 0, 0] ] start_x, start_y = 0, 0 end_x, end_y = 4, 4 result = bfs_shortest_path(maze, start_x, start_y, end_x, end_y) print(f"The shortest path length is {result}") # 应该输出 The shortest path length is 8 ``` 此代码实现了使用BFS解决迷宫最短路径的问题,并能有效处理各种复杂情况下的输入数据[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值