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

C++ 宽度优先搜索 || 模版题:走迷宫

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

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

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

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

输入格式
第一行包含两个整数 n
和 m

接下来 n
行,每行包含 m
个整数(0
或 1
),表示完整的二维数组迷宫。

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

数据范围
1≤n,m≤100
输入样例:
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

#include <iostream>
#include <cstring>
#include <algorithm>using namespace std;const int N = 110;typedef pair<int, int> PII;int n, m;
int g[N][N];
int d[N][N];
PII q[N * N];int bfs()
{int hh = 0, tt = 0;q[0] = {0, 0};memset(d, -1, sizeof d);d[0][0] = 0;int dx[4] = {0, 1, 0, -1}, dy[4] = {1, 0, -1, 0};while(hh <= tt){auto t = q[hh ++ ];for(int i = 0; i < 4; i ++ ){int x = t.first + dx[i], y = t.second + dy[i];if(x >= 0 && x < n && y >= 0 && y < m && g[x][y] == 0 && d[x][y] == -1){d[x][y] = d[t.first][t.second] + 1;q[ ++ tt] = {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 < m; j ++ )cin>>g[i][j];cout<<bfs()<<endl;return 0;
}

1、在 BFS 过程中,d[x][y] 表示从起点 (0, 0) 到达坐标 (x, y) 的最短路径长度。初始时,d[0][0] 被设置为 0,表示起点本身。然后,BFS 逐步遍历周围的单元格,并在发现更短的路径时更新 d 数组。

在代码中,d[x][y] 的值是通过 d[t.first][t.second] + 1 计算得到的,其中 (t.first, t.second) 是队列中当前处理的点。这里 +1 表示从当前点到下一个相邻点的距离,因为每一步的移动距离都是 1。

由于 BFS 的性质,它首次遇到目标点时,已经保证是最短路径,因为 BFS 会先扩展所有距离为 1 的点,然后是距离为 2 的点,以此类推。因此,一旦到达目标点,d[n - 1][m - 1] 就是最短路径的长度。

这样的设计保证了在遍历过程中每个点的最短路径都会被计算,并且队列按照距离的递增顺序进行遍历。

2、while 循环运行直到队列为空,是指 BFS 算法的主循环。BFS(广度优先搜索)是一种图的遍历算法,用于在图或者二维矩阵中找到从起点到终点的最短路径。

具体来说,BFS通过队列来进行遍历,队列中存放的是待探索的节点。初始时,将起点加入队列,然后不断从队列中取出一个节点进行探索,将其相邻且未访问过的节点加入队列,如此往复,直到队列为空。

在这个代码中,q 是用于 BFS 的队列,hh 和 tt 分别表示队列的头和尾。q[hh] 表示队列头部的节点,q[tt] 表示队列尾部的节点。在这个具体的问题中,队列中存放的是二维坐标 (x, y),表示矩阵中的某个点。

主循环的 while (hh <= tt) 保证了在队列非空的情况下继续循环。循环的目的是不断地取出队头的节点,然后探索其相邻的未访问过的节点,将它们加入队列,依此类推,直到队列为空。这样,通过队列的广度优先搜索,算法会逐层地从起点向终点扩展,最终计算出每个点到起点的最短路径。

队列的变化是通过不断取出队头节点、探索相邻节点、将未访问的相邻节点加入队列来实现的。整个过程保证了所有可达的节点都被访问到,而且是按照从起点到终点的最短路径进行访问的。

相关文章:

  • Oracle全系列版本官网下载保姆及教程
  • 高级分布式系统-第15讲 分布式机器学习--联邦学习
  • Spring Boot整合Junit
  • Elasticsearch 索引文档时create、index、update的区别【学习记录】
  • 23111 IO进程线程 day6
  • Linux学习记录——삼십구 数据链路层协议
  • Linux/Uinx 什么是栈帧?
  • 【b站咸虾米】新课uniapp零基础入门到项目打包(微信小程序/H5/vue/安卓apk)全掌握
  • Linux中的高级权限
  • 嵌入式linux_C应用学习之API函数
  • Qt QTableView和QStandardItemModel包含搜索出现的文本及隐藏顶层节点
  • 倍福嵌入式PLC开发团队建设
  • 程序设计语言的基本成分
  • 【IC前端虚拟项目】MVU寄存器文档编写与RTL代码生成
  • 【现代控制理论笔记】——第四章:能观性分析
  • [deviceone开发]-do_Webview的基本示例
  • bearychat的java client
  • CSS3 聊天气泡框以及 inherit、currentColor 关键字
  • EventListener原理
  • JavaScript标准库系列——Math对象和Date对象(二)
  • JS 面试题总结
  • Lsb图片隐写
  • maven工程打包jar以及java jar命令的classpath使用
  • node-glob通配符
  • PhantomJS 安装
  • react 代码优化(一) ——事件处理
  • Swoft 源码剖析 - 代码自动更新机制
  • unity如何实现一个固定宽度的orthagraphic相机
  • vuex 学习笔记 01
  • vue从入门到进阶:计算属性computed与侦听器watch(三)
  • zookeeper系列(七)实战分布式命名服务
  • 从零到一:用Phaser.js写意地开发小游戏(Chapter 3 - 加载游戏资源)
  • 从伪并行的 Python 多线程说起
  • 分布式事物理论与实践
  • 浮现式设计
  • 记一次删除Git记录中的大文件的过程
  • 理清楚Vue的结构
  • 前端面试之闭包
  • 前嗅ForeSpider采集配置界面介绍
  • 强力优化Rancher k8s中国区的使用体验
  • 实现简单的正则表达式引擎
  • 提升用户体验的利器——使用Vue-Occupy实现占位效果
  • HanLP分词命名实体提取详解
  • LIGO、Virgo第三轮探测告捷,同时探测到一对黑洞合并产生的引力波事件 ...
  • ​七周四次课(5月9日)iptables filter表案例、iptables nat表应用
  • ​软考-高级-系统架构设计师教程(清华第2版)【第15章 面向服务架构设计理论与实践(P527~554)-思维导图】​
  • %3cscript放入php,跟bWAPP学WEB安全(PHP代码)--XSS跨站脚本攻击
  • (10)ATF MMU转换表
  • (2021|NIPS,扩散,无条件分数估计,条件分数估计)无分类器引导扩散
  • (附源码)spring boot基于小程序酒店疫情系统 毕业设计 091931
  • (附源码)ssm经济信息门户网站 毕业设计 141634
  • (九十四)函数和二维数组
  • (转)树状数组
  • (转)一些感悟
  • .babyk勒索病毒解析:恶意更新如何威胁您的数据安全