AcWing走迷宫-最短路问题-BFS求解

题目描述

给定一个 n * m 的二维整数数组,用来表示一个迷宫,数组中只包含 01,其中 0 表示可以走的路,1 表示不可通过的墙壁。

最初,有一个人位于左上角 (1, 1) 处,已知该人每次可以向上、下、左、右任意一个方向移动一个位置。

请问,该人从左上角移动至右下角 (n, m) 处,至少需要移动多少次。

数据保证 (1, 1) 处和 (n, m) 处的数字为 0,且一定至少存在一条通路。


输入格式

  • 第一行包含两个整数 nm
  • 接下来 n 行,每行包含 m 个整数(01),表示完整的二维数组迷宫。

输出格式

输出一个整数,表示从左上角移动至右下角的最少移动次数。


数据范围

  • 1 ≤ n, m ≤ 100

输入输出样例

样例输入 1

复制

5 5
0 1 0 0 0
0 1 0 1 0
0 0 0 0 0
0 1 1 1 0
0 0 0 1 0
样例输出 1

复制

8

实现思路:
我么使用一个队列存储可能的路径(x,y),每次拿队头的元素判断下一步可以走的位置,如果可以走且之前没有走过,那么将该坐标放入队尾。当队列不为空就说明有位置可以走,就一直走下去,当所有位置都走完时,右下角的距离就是最短路径。

这个队列中的元素是个坐标,所以可以用pair类型存储,同时队列的实现可以通过数组+头尾指针实现:队头用hh标记,队尾用tt标记,开始都初始化为0,拿出队头元素t:PII t = q[hh++](先拿出来队头hh再++),当对头的下一个位置满足条件时,将其放入队尾q[++tt]={x,y};(队尾先++再赋值)

代码实现

#include<iostream>
using namespace std;
const int N = 110;
typedef pair<int, int> PII;
//g用于存储图,d用于记录每个坐标到初始位置的最短距离
int g[N][N], d[N][N];
int n, m;
PII q[N * N];  //q用于存储每个符合条件的坐标,(即路径)int bfs()
{//头尾指针,用于指向模拟队列int head = 0, tail = 0;q[0] = { 0,0 };  //首先从下标0,0位置开始memset(d, -1, sizeof d); //先将d初始话为-1d[0][0] = 0;  //0,0坐标到0,0的距离当然是0啦/** dx和dy用于记录上下左右四个方向* 如dx[0]dy[0]就表示x-1,y,即向上以一格*/int dx[4] = { -1,0,1,0 }, dy[4] = { 0,1,0,-1 }; while (head <= tail){//先获取队列头顶元素,再head++将其出队auto t = q[head++];for (int i = 0; i < 4; i++){//表示枚举该坐标的4个方向int x = t.first + dx[i];int y = t.second + dy[i];//如果这个位置为0(可以走),x<n,y<m(没出界),d[x][y]==-1(没被走过)if (g[x][y] == 0 && x < n && y < m && d[x][y] == -1){//该坐标下的最短路就是上一个坐标的长度+1d[x][y] = d[t.first][t.second] + 1;q[++tail] = { x,y }; //将其入队}}}return d[n - 1][m - 1];
}
int main()
{cin >> n >> m;for (int i = 0; i < n; i++)for (int j = 0; j < n; j++)cin >> g[i][j];cout << bfs() << endl;return 0;
}

代码思路总结

通过 广度优先搜索(BFS) 解决了迷宫最短路径问题。以下是代码的详细思路总结:


1. 问题分析

  • 给定一个 n * m 的二维数组表示迷宫,0 表示通路,1 表示墙壁。
  • 从起点 (0, 0) 出发,每次可以向上、下、左、右移动一个位置,求到达终点 (n-1, m-1) 的最短路径长度。

2. 核心思路

  • 使用 BFS 逐层遍历迷宫,确保第一次到达终点时的路径是最短的。
  • 使用一个队列来存储待访问的节点,并通过一个二维数组 d 记录每个节点到起点的最短距离。

3. 代码实现步骤

(1) 初始化
  • 定义二维数组 g 存储迷宫,d 存储每个节点到起点的最短距离。
  • 使用 pair<int, int> 表示坐标,并用数组 q 模拟队列。
  • 初始化队列 q,将起点 (0, 0) 加入队列,并设置 d[0][0] = 0
(2) BFS 遍历
  • 使用 while 循环不断从队列中取出节点,直到队列为空。
  • 对于每个节点,枚举其四个方向(上、下、左、右):
    • 计算新坐标 (x, y)
    • 检查新坐标是否合法(未越界、是通路 0、未被访问过 d[x][y] == -1)。
    • 如果合法,更新新坐标的最短距离,并将其加入队列。
(3) 终止条件
  • 当遍历到终点 (n-1, m-1) 时,d[n-1][m-1] 即为最短路径长度。

4. 代码细节解析

(1) 队列的实现
  • 使用数组 q 模拟队列,headtail 分别表示队头和队尾指针。
  • 入队操作:q[++tail] = {x, y}
  • 出队操作:auto t = q[head++]
(2) 方向数组
  • 使用 dxdy 数组表示四个方向的偏移量:

    cpp

    复制

    int dx[4] = {-1, 0, 1, 0}; // 上、右、下、左
    int dy[4] = {0, 1, 0, -1};
    
  • 通过循环枚举四个方向,简化代码。

(3) 距离数组 d
  • d[i][j] 表示从起点 (0, 0)(i, j) 的最短距离。
  • 初始时,d 数组全部初始化为 -1,表示未访问。
  • 每次更新新坐标的距离:d[x][y] = d[t.first][t.second] + 1
(4) 边界检查
  • 检查新坐标 (x, y) 是否在迷宫范围内:

    cpp

    复制

    x < n && y < m
    
  • 检查新坐标是否是通路:

    cpp

    复制

    g[x][y] == 0
    
  • 检查新坐标是否未被访问过:

    cpp

    复制

    d[x][y] == -1
    

5. 复杂度分析

(1) 时间复杂度
  • 每个节点最多被访问一次,因此时间复杂度为 O(n * m)
(2) 空间复杂度
  • 使用了一个队列和一个距离数组,空间复杂度为 O(n * m)

6. 示例运行

输入

复制

5 5
0 1 0 0 0
0 1 0 1 0
0 0 0 0 0
0 1 1 1 0
0 0 0 1 0
输出

复制

8

7. 总结

  • 通过 BFS 实现了迷宫最短路径的求解,利用了队列的先进先出特性,确保第一次到达终点时的路径是最短的。

算法刷题日记

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/70503.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

go 错误处理 error

普通错误处理 // 包路径 package mainimport ("errors""fmt" )func sqrt(f1, f2 float64) (float64, error) {if f2 < 0 {return 0, errors.New("error: f2 < 0")}return f1 / f2, nil }func sqrt1(f1, f2 float64) {if re, err : sqrt(f…

MCU Bootloader具备什么条件才能跳转到APP程序

在MCU系统中&#xff0c;BootLoader&#xff08;Boot&#xff09;跳转到应用程序&#xff08;APP&#xff09;的条件通常由硬件和软件协同控制&#xff0c;核心逻辑是确保APP的完整性和合法性。以下是关键条件及流程&#xff1a; 1. 硬件启动模式选择 BOOT引脚电平&#xff1a…

LeeCode题库第二十八题

28.找出字符串第一个匹配项的下标 项目场景&#xff1a; 给你两个字符串 haystack 和 needle &#xff0c;请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标&#xff08;下标从 0 开始&#xff09;。如果 needle 不是 haystack 的一部分&#xff0c;则返回 …

深入解析BFS算法:C++实现无权图最短路径的高效解决方案

在无权图中&#xff0c;广度优先搜索&#xff08;BFS&#xff09;是解决最短路径问题的高效算法。接下来博主从专业角度深入探讨其实现细节&#xff0c;并给出C代码示例&#xff1a; 目录 一、核心原理 二、算法步骤 三、C实现关键点 1. 数据结构 2. 边界检查 3. 路径回溯…

Plant Simulation培训教程-双深堆垛机立库仿真模块

原创 知行 天理智能科技 2025年01月03日 17:02 浙江 又到年终盘点的时候了&#xff0c;在这里我把之前录制的Plant Simulation培训教程-双深堆垛机立库仿真模块分享出来&#xff0c;有需要的可以直接联系我。 双深堆垛机立库仿真模块基于单深模块开发&#xff0c;适用于双深堆…

文本和语音互转

目录 1. 下载依赖ddl 2. 引入Pom依赖 3. java代码 二. 语音转文本 1. 下载中文语音转文本的模型 2. 引入pom依赖 3. java代码 4. 运行效果 1. 下载依赖ddl 文字转语音文件需要使用jacob的dll文件放在jdk安装目录下的bin文件夹下 点击官网下载录或者通过csdn下载 2. …

DeepSeek破局启示录:一场算法优化对算力霸权的降维打击

导言 2024年,中国AI大模型赛道杀出一匹黑马——深度求索(DeepSeek)。从数学推理能力超越GPT-4,到API价格仅为Claude 3.5的1/53,再到开源生态的快速扩张,DeepSeek的崛起不仅打破了“算力霸权”的固有认知,更揭示了AI行业底层逻辑的深刻变革。这场技术革命背后,隐藏着技术…

Python大数据可视化:基于python大数据的电脑硬件推荐系统_flask+Hadoop+spider

开发语言&#xff1a;Python框架&#xff1a;flaskPython版本&#xff1a;python3.7.7数据库&#xff1a;mysql 5.7数据库工具&#xff1a;Navicat11开发软件&#xff1a;PyCharm 系统展示 管理员登录 管理员功能界面 价格区间界面 用户信息界面 品牌管理 笔记本管理 电脑主机…

阿里云虚机的远程桌面登录提示帐户被锁定了

提示由于安全原因&#xff0c;帐户被锁定。 阿里云虚机ECS的远程桌面登录提示帐户被锁定了&#xff0c;只能登录阿里云处理 阿里云-计算&#xff0c;为了无法计算的价值 需选择通过VNC连接 然后计算机管理&#xff0c;解除帐户锁定即可。

Grok 使用指南

文章来源&#xff1a;Grok 漫游指南 | xAI Docs 欢迎&#xff01;在本指南中&#xff0c;我们将引导您了解使用 xAI API 的基础知识。 #第 1 步&#xff1a;创建 xAI 帐户 您需要一个 xAI 帐户才能访问 xAI API。在此处注册帐户。 创建账户后&#xff0c;您需要为其加载积分…

Node.js高频面试题精选及参考答案

目录 什么是 Node.js?它的主要特点有哪些? Node.js 的事件驱动和非阻塞 I/O 模型是如何工作的? 为什么 Node.js 适合处理高并发场景? Node.js 与传统后端语言(如 Java、Python)相比,有哪些优势和劣势? 简述 Node.js 的运行原理,包括 V8 引擎的作用。 什么是 Nod…

Servlet概述(Ⅰ)

目录 一、Servlet概述 演示 创建JavaWeb项目&#xff08;2017版本为例&#xff09; 1. 打开 IntelliJ IDEA 2. 选择项目类型 3. 配置框架 二、Servlet初识(熟练) 1.servlet说明 2.Servlet 接口方法 3.创建Servlet 4.JavaWeb请求响应流程 ​编辑 ​编辑 5.servlet…

Windows 小记 18 —— 子窗口继承父窗口的样式

子窗口会继承父窗口或者所有者窗口的一些样式。 当我们使用 CreateWindowExW 创建窗口后&#xff0c;指定其 HwndParent 参数时&#xff0c;或者通过 SetWindowLongPtr(vd->Hwnd, GWLP_HWNDPARENT, (LONG_PTR)vd->HwndParent); 指定所有者窗口时&#xff0c;子窗口将从父…

19、《Springboot+MongoDB整合:玩转文档型数据库》

SpringbootMongoDB整合&#xff1a;玩转文档型数据库 摘要&#xff1a;本文全面讲解Spring Boot与MongoDB的整合实践&#xff0c;涵盖环境搭建、CRUD操作、聚合查询、事务管理、性能优化等核心内容。通过15个典型代码示例&#xff0c;演示如何高效操作文档数据库&#xff0c;深…

跳跃游戏II(力扣45)

这道题在跳跃游戏(力扣55)-CSDN博客 的基础上需要找到最小的跳跃次数。那么我们需要用一个变量来统计跳跃次数&#xff0c;而难点就在于何时让该变量的值增加。这一点我写在注释中&#xff0c;大家结合我的代码会更好理解。其他部分跟跳跃游戏(力扣55)-CSDN博客 几乎相同&#…

Linux基础开发工具的使用(apt、vim、gcc、g++、gdb、make、makefile)

Linux软件包管理器–apt Linux安装软件的方式 在Linux下安装软件的方法有以下三种&#xff1a; 下载到程序的源代码&#xff0c;自己编译出可执行程序获取deb安装包、然后使用dpkg命令安装。&#xff08;不解决依赖关系&#xff09;通过apt进行安装软件。 小知识点&#xf…

C/C++ | 每日一练 (2)

&#x1f4a2;欢迎来到张胤尘的技术站 &#x1f4a5;技术如江河&#xff0c;汇聚众志成。代码似星辰&#xff0c;照亮行征程。开源精神长&#xff0c;传承永不忘。携手共前行&#xff0c;未来更辉煌&#x1f4a5; 文章目录 C/C | 每日一练 (2)题目参考答案封装继承多态虚函数底…

【前端框架】vue2和vue3的区别详细介绍

Vue 3 作为 Vue 2 的迭代版本&#xff0c;在性能、语法、架构设计等多个维度均有显著的变革与优化。以下详细剖析二者的区别&#xff1a; 响应式系统 Vue 2 实现原理&#xff1a;基于 Object.defineProperty() 方法实现响应式。当一个 Vue 实例创建时&#xff0c;Vue 会遍历…

基于Spring Boot的农事管理系统设计与实现(LW+源码+讲解)

专注于大学生项目实战开发,讲解,毕业答疑辅导&#xff0c;欢迎高校老师/同行前辈交流合作✌。 技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;…

【RISCV 常见汇编指令学习 1.2 -- CSRW | CSRR | XORI | ANDI | DRET | J | JR】

文章目录 Overview1. CSRW 与 CSRR2. SW 与 lw3. XORI 与 ANDI4. J 与 JR5. ret 与 dret6. 总结&#x1f310; Sources Overview 在 RISCV 汇编中&#xff0c;不同类型的指令用于完成控制寄存器操作、内存存取、位操作、跳转以及返回等功能。下面将逐对详细介绍这些指令&#…