当前位置: 首页 > news >正文

(算法竞赛)使用广度优先搜索(BFS)解决迷宫最短路径问题

在这个充满奇思妙想的世界里,每一次探索都像是打开了一扇通往新世界的大门。今天,我们将踏上一段特别的旅程,去揭开那些隐藏在代码、算法、数学谜题或生活智慧背后的秘密。🎉😊

所以,系好安全带,准备好迎接一场充满欢笑和惊喜的冒险吧!我们的故事,现在正式开始……

题目描述

当你站在一个迷宫里的时候,往往会被错综复杂的道路弄得失去方向感,如果你能得到迷宫地图,事情就会变得非常简单。假设你已经得到了一个 n x m 的迷宫的图纸,请你找出从起点到出口的最短路。

输入: 第一行是两个整数 n 和 m (1 ≤ n,m ≤ 100),表示迷宫的行数和列数。 接下来 n 行,每行一个长为 m 的字符串,表示整个迷宫的布局。字符’.‘表示空地,’#'表示墙,'S’表示起点,'T’表示出口。

输出: 输出从起点到出口最少需要走的步数。

样例: 输入:

复制

3 3
S#T
.#.
...

输出:

复制

6

来源: 深搜 递归 广搜

在解决迷宫问题时,尤其是寻找从起点到终点的最短路径时,广度优先搜索(BFS)是一种非常高效且常用的方法。本文将详细解析一个基于 BFS 的 Python 代码,帮助你理解其工作原理和实现细节。

1. 问题背景

迷宫问题是一个经典的路径搜索问题。给定一个二维迷宫,起点为 S,终点为 T,迷宫中包含可通行的格子(用 . 表示)和障碍物(用 # 表示)。目标是找到从起点到终点的最短路径长度。

2. 为什么选择 BFS?

广度优先搜索(BFS)是一种逐层扩展的搜索算法,适用于无权图(迷宫中每个格子的移动代价相同)的最短路径问题。BFS 的核心思想是从起点开始,逐层扩展所有可能的路径,直到找到终点。由于 BFS 按层扩展,最先到达终点的路径一定是最短路径。

3. 代码解析
3.1 输入迷宫数据

Python复制

# 输入网格的行数和列数
n, m = map(int, input().split())
# 输入网格状态
a = [list(input()) for _ in range(n)]
  • 这部分代码首先读取迷宫的行数 n 和列数 m

  • 然后逐行读取迷宫的布局,存储为一个二维字符数组 a。每个格子的值可以是:

    • S:起点。

    • T:终点。

    • .:可通行的格子。

    • #:障碍物。

3.2 定义方向数组

Python复制

# 定义方向数组
dx = [0, 0, 1, -1]  # 行变化(右、左、下、上)
dy = [1, -1, 0, 0]  # 列变化
  • 这两个数组定义了四个可能的移动方向:右、左、下、上。

  • 通过索引 i,可以从 dxdy 中获取对应方向的行和列偏移量。

3.3 找到起点和终点

Python复制

# 找到起点 'S' 和终点 'T' 的位置
start_x, start_y = None, None
end_x, end_y = None, None
for i in range(n):for j in range(m):if a[i][j] == 'S':start_x, start_y = i, jelif a[i][j] == 'T':end_x, end_y = i, j
  • 遍历迷宫,找到起点 S 和终点 T 的坐标。

  • 如果迷宫中不存在起点或终点,程序将无法正常运行,因此需要确保输入的迷宫包含 ST

3.4 初始化访问标记数组

Python复制

# 初始化访问标记数组
vis = [[False] * m for _ in range(n)]
  • 创建一个与迷宫大小相同的二维数组 vis,用于记录每个格子是否被访问过。

  • 初始时,所有格子标记为未访问(False)。

3.5 BFS 函数实现

Python复制

from collections import dequedef bfs(start_x, start_y):queue = deque([(start_x, start_y, 0)])  # 队列中存储 (x, y, 步数)vis[start_x][start_y] = True  # 标记起点为已访问while queue:xx, yy, steps = queue.popleft()  # 当前格子及步数# 如果到达终点,返回步数if xx == end_x and yy == end_y:return steps# 遍历四个方向for i in range(4):x, y = xx + dx[i], yy + dy[i]if 0 <= x < n and 0 <= y < m and not vis[x][y] and a[x][y] != '#':vis[x][y] = True  # 标记为已访问queue.append((x, y, steps + 1))  # 加入队列并步数加1return -1  # 如果没有找到路径,返回 -1
  • 队列初始化:使用 deque 创建一个队列,初始时将起点 (start_x, start_y) 和步数 0 加入队列。

  • 逐层扩展:从队列中取出一个格子 (xx, yy),检查是否到达终点。如果是,则返回当前步数。

  • 扩展相邻格子:对于当前格子的四个相邻格子,检查是否在迷宫范围内、未被访问且不是障碍物。如果是,则标记为已访问,并将其加入队列,步数加1。

  • 回溯:如果队列为空且未找到终点,返回 -1,表示无路径。

3.6 调用 BFS 并输出结果

Python复制

# 从起点开始 BFS
if start_x is not None and end_x is not None:shortest_path = bfs(start_x, start_y)print(shortest_path)
else:print("未找到起点或终点")
  • 调用 bfs 函数,从起点开始搜索。

  • 如果找到最短路径,输出路径长度;否则,输出提示信息。

4. 代码运行逻辑
  1. 初始化:读取迷宫数据,找到起点和终点,初始化访问标记数组。

  2. BFS 搜索

    • 从起点开始,逐层扩展所有可能的路径。

    • 使用队列存储当前层的格子及其步数。

    • 每次从队列中取出一个格子,检查是否到达终点。

    • 如果未到达终点,扩展其相邻格子,并将未访问的格子加入队列。

  3. 终止条件

    • 如果到达终点,返回当前步数。

    • 如果队列为空且未找到终点,返回 -1

5. 输入输出示例
输入:

复制

3 3
S#T
.#.
...
输出:
4
6. BFS 的优势
  • 时间复杂度:BFS 的时间复杂度为 O(n×m),适合迷宫规模较大的情况。

  • 空间复杂度:BFS 的空间复杂度为 O(n×m),主要用于存储访问标记数组和队列。

  • 最短路径保证:BFS 按层扩展,最先到达终点的路径一定是最短路径。

7. 总结

本文通过详细解析基于 BFS 的代码,展示了如何高效地解决迷宫最短路径问题。BFS 的逐层扩展特性使其成为解决此类问题的理想选择。通过合理使用队列和访问标记数组,代码能够高效地找到从起点到终点的最短路径,而不会出现超时问题。

完整代码

from collections import deque# 输入网格的行数和列数
n, m = map(int, input().split())
# 输入网格状态
a = [list(input()) for _ in range(n)]# 定义方向数组
dx = [0, 0, 1, -1]  # 行变化(右、左、下、上)
dy = [1, -1, 0, 0]  # 列变化# 找到起点 'S' 和终点 'T' 的位置
start_x, start_y = None, None
end_x, end_y = None, None
for i in range(n):for j in range(m):if a[i][j] == 'S':start_x, start_y = i, jelif a[i][j] == 'T':end_x, end_y = i, j# 初始化访问标记数组
vis = [[False] * m for _ in range(n)]# BFS 函数
def bfs(start_x, start_y):queue = deque([(start_x, start_y, 0)])  # 队列中存储 (x, y, 步数)vis[start_x][start_y] = True  # 标记起点为已访问while queue:xx, yy, steps = queue.popleft()  # 当前格子及步数# 如果到达终点,返回步数if xx == end_x and yy == end_y:return steps# 遍历四个方向for i in range(4):x, y = xx + dx[i], yy + dy[i]if 0 <= x < n and 0 <= y < m and not vis[x][y] and a[x][y] != '#':vis[x][y] = True  # 标记为已访问queue.append((x, y, steps + 1))  # 加入队列并步数加1return -1  # 如果没有找到路径,返回 -1# 从起点开始 BFS
if start_x is not None and end_x is not None:shortest_path = bfs(start_x, start_y)print(shortest_path)
else:print("未找到起点或终点")

队列知识及其在广度优先搜索(BFS)中的应用

队列(Queue)是一种先进先出(First-In-First-Out,FIFO)的数据结构,广泛应用于算法和程序设计中。理解队列的使用,尤其是它在广度优先搜索(BFS)中的关键作用,对于解决路径搜索问题(如迷宫问题)至关重要。


1. 队列的基本概念

队列是一种线性数据结构,其操作类似于现实生活中的排队场景。队列的主要操作包括:

  • 入队(Enqueue):在队列的尾部添加一个元素。

  • 出队(Dequeue):从队列的头部移除一个元素。

  • 查看队头(Peek/Front):查看队列头部的元素,但不移除它。 

队列的特点是先进先出,即最早进入队列的元素会最先被移除。


5. 使用队列的 BFS 与不使用队列的 DFS 的对比

特性BFS(使用队列)DFS(不使用队列)
扩展顺序逐层扩展深度优先
数据结构队列(先进先出)栈(后进先出)
适用场景最短路径问题所有路径问题
时间复杂度O(n×m)O(4n×m)
空间复杂度O(n×m)O(n×m)

 6. 总结

队列是 BFS 的核心数据结构,它通过先进先出的特性确保了 BFS 的逐层扩展。在解决最短路径问题时,BFS 使用队列能够高效地找到从起点到终点的最短路径,而不会像 DFS 那样因深度优先搜索而导致超时。理解队列的使用,对于掌握 BFS 算法至关重要。

希望这篇文章能帮助你更好地理解队列在 BFS 中的应用。如果你对队列或 BFS 仍有疑问,欢迎随时提问!

相关文章:

(算法竞赛)使用广度优先搜索(BFS)解决迷宫最短路径问题

在这个充满奇思妙想的世界里&#xff0c;每一次探索都像是打开了一扇通往新世界的大门。今天&#xff0c;我们将踏上一段特别的旅程&#xff0c;去揭开那些隐藏在代码、算法、数学谜题或生活智慧背后的秘密。&#x1f389;&#x1f60a; 所以&#xff0c;系好安全带&#xff0…...

Sqoop源码修改:增加落地HDFS文件数与MapTask数量一致性检查

个人博客地址&#xff1a;Sqoop源码修改&#xff1a;增加落地HDFS文件数与MapTask数量一致性检查 | 一张假钞的真实世界 本篇是对记录一次Sqoop从MySQL导入数据到Hive问题的排查经过的补充。 Sqoop 命令通过 bin 下面的脚本调用&#xff0c;调用如下&#xff1a; exec ${HAD…...

嵌入式系统|DMA和SPI

文章目录 DMA&#xff08;直接内存访问&#xff09;DMA底层原理1. 关键组件2. 工作机制3. DMA传输模式 SPI&#xff08;串行外设接口&#xff09;SPI的基本原理SPI连接示例 DMA与SPI的共同作用 DMA&#xff08;直接内存访问&#xff09; 类型&#xff1a;DMA是一种数据传输接口…...

leetcode——将有序数组转化为二叉搜索树(java)

给你一个整数数组 nums &#xff0c;其中元素已经按 升序 排列&#xff0c;请你将其转换为一棵 平衡 二叉搜索树。 示例 1&#xff1a; 输入&#xff1a;nums [-10,-3,0,5,9] 输出&#xff1a;[0,-3,9,-10,null,5] 解释&#xff1a;[0,-10,5,null,-3,null,9] 也将被视为正确答…...

冯诺依曼结构和进程概念及其相关的内容的简单介绍

目录 ​编辑 冯诺依曼体系结构 操作系统(Operator System) 进程 引入 基本概念 描述进程-PCB task_ struct内容分类 进程 ID (PID)和查看进程 进程状态: 进程创建: 进程终止: 进程间通信 (IPC): 冯诺依曼体系结构 冯诺依曼体系结构是现代计算机的基础架构&#xf…...

Native Memory Tracking 与 RSS的差异问题

一 问题现象 前一段时间用nmt查看jvm进程的栈区占用的内存大小。测试代码如下 public class ThreadOOM {public static void main(String[] args) {int i 1;while (i < 3000) {Thread thread new TestThread();thread.start();System.out.println("thread : "…...

在K8s中部署动态nfs存储provisioner

背景 之前&#xff0c;我已经在一台worker node上安装了local lvm 的provisioner来模拟需要本地高IOPS的数据库等stafeful应用的实现。 为了后续给虚拟机里的K8s集群安装可用的metrics和logs监控系统&#xff08;metrics和logs的时序数据库需要永久存储&#xff09;&#xff0…...

家庭财务管理系统的设计与实现

标题:家庭财务管理系统的设计与实现 内容:1.摘要 摘要&#xff1a;随着家庭经济的日益复杂&#xff0c;家庭财务管理变得越来越重要。本文旨在设计并实现一个功能强大的家庭财务管理系统&#xff0c;以帮助用户更好地管理家庭财务。通过对家庭财务管理需求的分析&#xff0c;我…...

数据结构-Stack和栈

1.栈 1.1什么是栈 栈是一种特殊的线性表&#xff0c;只允许在固定的一段进行插入和删除操作&#xff0c;进行插入和删除操作的一段称为栈顶&#xff0c;另一端称为栈底。 栈中的数据元素遵顼后进先出LIFO&#xff08;Last In First Out&#xff09;的原则&#xff0c;就像一…...

使用vhd虚拟磁盘安装两个win10系统

使用vhd虚拟磁盘安装两个win10系统 前言vhd虚拟磁盘技术简介准备工具开始动手实践1.winX选择磁盘管理2.选择“操作”--“创建VHD”3.自定义一个位置&#xff0c;输入虚拟磁盘大小4.右键初始化磁盘5.选择GPT分区表格式6.右键新建简单卷7.给卷起个名字&#xff0c;用于区分8.打开…...

代码随想录34 动态规划

1.经典问题&#xff1a; 背包问题 打家劫舍 斐波那契数列 爬楼梯问题 股票问题 2.dp数组以及下标的含义 3.递推公式 3.dp数组初始化 4.遍历顺序 5.打印数组 leetcode509.斐波那契数列 1.确定dp[i]含义 dp[i]第i个斐波那契数的值为dp[i] 2.递推公式&#xff1a;dp[…...

【2025年最新版】Java JDK安装、环境配置教程 (图文非常详细)

文章目录 【2025年最新版】Java JDK安装、环境配置教程 &#xff08;图文非常详细&#xff09;1. JDK介绍2. 下载 JDK3. 安装 JDK4. 配置环境变量5. 验证安装6. 创建并测试简单的 Java 程序6.1 创建 Java 程序&#xff1a;6.2 编译和运行程序&#xff1a;6.3 在显示或更改文件的…...

Shell特殊状态变量以及常用内置变量总结

目录 1. 特殊的状态变量 1.1 $?&#xff08;上一个命令的退出状态&#xff09; 1.2 $$&#xff08;当前进程的 PID&#xff09; 1.3 $!&#xff08;后台进程的 PID&#xff09; 1.4 $_&#xff08;上一条命令的最后一个参数&#xff09; 2.常用shell内置变量 2.1 echo&…...

【4Day创客实践入门教程】Day4 迈向高手之路——进一步学习!

Day4 迈向高手之路——进一步学习&#xff01; 目录 Day4 迈向高手之路——进一步学习&#xff01;更多的开发板外壳制作 Day0 创想启程——课程与项目预览Day1 工具箱构建——开发环境的构建Day2 探秘微控制器——单片机与MicroPython初步Day3 实战演练——桌面迷你番茄钟Day4…...

EtherCAT-快速搭建

EtherCAT-快速搭建 快速简介 快速简介 EtherCAT现场总线协议是由德国倍福公司在2003年提出的&#xff0c;该通讯协议拓扑结构十分灵活&#xff0c;数据传输速度快&#xff0c;同步特性好&#xff0c;可以形成各种网络拓扑结构。倍福公司推出了自己的ASIC专用芯片有ET1100和ET1…...

【设计测试用例自动化测试性能测试 实战篇】

&#x1f308;个人主页&#xff1a;努力学编程’ ⛅个人推荐&#xff1a; c语言从初阶到进阶 JavaEE详解 数据结构 ⚡学好数据结构&#xff0c;刷题刻不容缓&#xff1a;点击一起刷题 &#x1f319;心灵鸡汤&#xff1a;总有人要赢&#xff0c;为什么不能是我呢 设计测试用例…...

DBeaver连接MySQL提示Access denied for user ‘‘@‘ip‘ (using password: YES)的解决方法

在使用DBeaver连接MySQL数据库时&#xff0c;如果遇到“Access denied for user ip (using password: YES)”的错误提示&#xff0c;说明用户认证失败。此问题通常与数据库用户权限、配置错误或网络设置有关。本文将详细介绍解决此问题的步骤。 一、检查用户名和密码 首先&am…...

【MySQL — 数据库增删改查操作】深入解析MySQL的 Update 和 Delete 操作

1. 测试数据 mysql> select* from exam1; ----------------------------------------- | id | name | Chinese | Math | English | ----------------------------------------- | 1 | 唐三藏 | 67.0 | 98.0 | 56.0 | | 2 | 孙悟空 | 87.0 | 78.…...

04树 + 堆 + 优先队列 + 图(D1_树(D1_基本介绍))

目录 一、什么是树&#xff1f; 二、相关术语 根结点 边 叶子结点 兄弟结点 祖先结点 结点的大小 树的层 结点的深度 结点的高度 树的高度 斜树 一、什么是树&#xff1f; 树是一种类似于链表的数据结构&#xff0c;不过链表的结点是以线性方式简单地指向其后继结…...

【Proteus仿真】【51单片机】多功能计算器系统设计

目录 一、主要功能 二、使用步骤 三、硬件资源 四、软件设计 五、实验现象 联系作者 一、主要功能 1、LCD1602液晶显示 2、矩阵按键​ 3、加减乘除&#xff0c;开方运算 4、带符号运算 5、最大 999*999 二、使用步骤 基于51单片机多功能计算器 包含&#xff1a;程序&…...

阿里云ACP云计算备考笔记 (5)——弹性伸缩

目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...

vue3 字体颜色设置的多种方式

在Vue 3中设置字体颜色可以通过多种方式实现&#xff0c;这取决于你是想在组件内部直接设置&#xff0c;还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法&#xff1a; 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...

成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战

在现代战争中&#xff0c;电磁频谱已成为继陆、海、空、天之后的 “第五维战场”&#xff0c;雷达作为电磁频谱领域的关键装备&#xff0c;其干扰与抗干扰能力的较量&#xff0c;直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器&#xff0c;凭借数字射…...

C++ Visual Studio 2017厂商给的源码没有.sln文件 易兆微芯片下载工具加开机动画下载。

1.先用Visual Studio 2017打开Yichip YC31xx loader.vcxproj&#xff0c;再用Visual Studio 2022打开。再保侟就有.sln文件了。 易兆微芯片下载工具加开机动画下载 ExtraDownloadFile1Info.\logo.bin|0|0|10D2000|0 MFC应用兼容CMD 在BOOL CYichipYC31xxloaderDlg::OnIni…...

【Go语言基础【12】】指针:声明、取地址、解引用

文章目录 零、概述&#xff1a;指针 vs. 引用&#xff08;类比其他语言&#xff09;一、指针基础概念二、指针声明与初始化三、指针操作符1. &&#xff1a;取地址&#xff08;拿到内存地址&#xff09;2. *&#xff1a;解引用&#xff08;拿到值&#xff09; 四、空指针&am…...

推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材)

推荐 github 项目:GeminiImageApp(图片生成方向&#xff0c;可以做一定的素材) 这个项目能干嘛? 使用 gemini 2.0 的 api 和 google 其他的 api 来做衍生处理 简化和优化了文生图和图生图的行为(我的最主要) 并且有一些目标检测和切割(我用不到) 视频和 imagefx 因为没 a…...

CSS | transition 和 transform的用处和区别

省流总结&#xff1a; transform用于变换/变形&#xff0c;transition是动画控制器 transform 用来对元素进行变形&#xff0c;常见的操作如下&#xff0c;它是立即生效的样式变形属性。 旋转 rotate(角度deg)、平移 translateX(像素px)、缩放 scale(倍数)、倾斜 skewX(角度…...

uniapp 开发ios, xcode 提交app store connect 和 testflight内测

uniapp 中配置 配置manifest 文档&#xff1a;manifest.json 应用配置 | uni-app官网 hbuilderx中本地打包 下载IOS最新SDK 开发环境 | uni小程序SDK hbulderx 版本号&#xff1a;4.66 对应的sdk版本 4.66 两者必须一致 本地打包的资源导入到SDK 导入资源 | uni小程序SDK …...

HubSpot推出与ChatGPT的深度集成引发兴奋与担忧

上周三&#xff0c;HubSpot宣布已构建与ChatGPT的深度集成&#xff0c;这一消息在HubSpot用户和营销技术观察者中引发了极大的兴奋&#xff0c;但同时也存在一些关于数据安全的担忧。 许多网络声音声称&#xff0c;这对SaaS应用程序和人工智能而言是一场范式转变。 但向任何技…...

从零开始了解数据采集(二十八)——制造业数字孪生

近年来&#xff0c;我国的工业领域正经历一场前所未有的数字化变革&#xff0c;从“双碳目标”到工业互联网平台的推广&#xff0c;国家政策和市场需求共同推动了制造业的升级。在这场变革中&#xff0c;数字孪生技术成为备受关注的关键工具&#xff0c;它不仅让企业“看见”设…...