【第十九课】BFS:广度优先搜索 (acwing-844走迷宫 / 含过程演示的视频推荐 / c++代码)

目录

BFS思路

可能需要看的视频和博客

代码如下

输出最短路径途径点


 

关于这种类型的题,我是有点印象的。。。当时蓝桥杯校内选拔就有这种题,当时还没学算法hhh

BFS思路

对应上图来理解BFS的方式还是很容易的,只是如何在题目中应用BFS的思想来解决问题呢?从具体的树的模型框架来看还容易理解,可是如果到了题目中这种二维数组走迷宫的形式,又该如何将我们已经理解的BFS思想对应到这种题目里面呢? 

在走迷宫问题中,

我们可以将每一个可能的步骤或者位置看作是树的一个节点,因为我们每移动一个位置,都会距起始位置远一点,每到一个新的位置,就相当于到达了树的新的一层。

如果有多个具有相同地位的满足条件的位置,这些位置就可以看做是同一层的节点。

起始位置是根节点。每一次移动都相当于从当前节点到达子节点。

通过上面的叙述相信对这种方法的实际应用有了大概的思路。

可能需要看的视频和博客

下面这两个视频里有详细的走迷宫问题的广度优先搜索的动态过程非常推荐看一下,会对BFS在迷宫问题里与在树的结构 之间的联系有更清晰的理解。

【【信息学奥赛教程】广度优先搜索算法 - 走迷宫】

【【直观的算法】如何用最短的路径走出迷宫】

我们这里用到数组模拟队列,需要回顾的可以看之前写的这篇文章

【第十一课】数组模拟栈和队列 / 单调栈 / 单调队列(滑动窗口) (c++代码 / 思路 )(acwing-828,829,830,154)

其实用数组模拟栈和队列甚至链表,其实主要就是运用数组的结构,但是更改数组下标的含义,这样的思路来模拟的。 

代码如下

#include<iostream>
#include<cstring>//memset函数的头文件
using namespace std;typedef pair<int,int> PII;//定义 坐标对
const int N=110;
int n,m;
int g[N][N];//存储二维迷宫
int d[N][N];//存储从起点到达 每个被访问过的位置 的最短路径长度
PII q[N*N];//创建N*N大小的队列,足以容纳整个迷宫的每个位置
int bfs()
{int hh=0,tt=0;//定义队头和队尾q[0]={0,0};//将起始点存入队列memset(d,-1,sizeof d);//初始化迷宫所有的点为-1 表示未被访问过d[0][0]=0;//起始点标记为0 表示已访问,并且起始点到(0,0) (也就是其自身)的最短路径长度为0//表示在二维坐标系中,某点的四个相邻位置的 偏移量int dx[4]={-1,0,1,0};int dy[4]={0,1,0,-1};while(hh<=tt)//只要队列中还有 待寻找下一个满足条件的节点 的当前节点时,就继续执行循环{PII t=q[hh++];//将队头元素出队for(int i=0;i<4;i++){//由于t是pair类型,可以由.first/.second访问元素(这里元素也就是x y坐标)//  由原来的坐标加上偏移量就得出四个方向上的坐标int x=t.first+dx[i];int y=t.second+dy[i];//首先要满足在迷宫大小范围内的可以通过的点(即g为0),并且未被访问过(保证了最短路)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()
{scanf("%d%d",&n,&m);for(int i=0;i<n;i++){for(int j=0;j<m;j++){scanf("%d",&g[i][j]);}}printf("%d",bfs());return 0;
}

很多需要解释的都写在注释里了。

我们在对这个迷宫进行广搜的时候,其实会遍历迷宫中的所有可以走的位置。因此可以说 d 数组是用来存储从起点到达二维网格中每个点所对应的最短路径长度

我们是如何实现遍历所有可以走的位置呢?

在while循环内部,对每一个节点进行for循环遍历其周围的四个节点,如果有多种方向可选会发生什么?

上面的这两个问题其实互为对方的答案。

就是因为我们对每个方向都进行判断,或有多种可能的路径选择,才会将所有可以走的位置都遍历过,并且d数组的作用也可以用 “记录所有可行的点到起始点的最短距离”这一说法进行描述。

输出最短路径途径点

在前面代码基础上,做了一些添加。修改的的地方有注释。

#include<iostream>
#include<cstring>
using namespace std;
typedef pair<int,int> PII;
const int N=120;
int n,m;
int g[N][N],d[N][N];
PII q[N*N];
PII p[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]={-1,0,1,0};int dy[4]={0,1,0,-1};while(hh<=tt){PII t=q[hh++];for(int i=0;i<4;i++){int x=t.first+dx[i];int y=t.second+dy[i];if(x>=0 && x<n && y>=0 && y<m && d[x][y]==-1 && g[x][y]==0){d[x][y]=d[t.first][t.second]+1;p[x][y]=t;//记录前驱节点,表明是从位置 t 移动到 (x, y) 的q[++tt]={x,y};}}}//倒着输出最短路径的途径坐标点int x=n-1,y=m-1;while(x||y){cout<<x<<" "<<y<<endl;auto t=p[x][y];x=t.first,y=t.second;}return d[n-1][m-1];
}
int main()
{scanf("%d%d",&n,&m);for(int i=0;i<n;i++){for(int j=0;j<n;j++){scanf("%d",&g[i][j]);}}cout<<bfs()<<endl;return 0;
}

这个不难理解,仔细想一下哦。


BFS先写到这。 

有问题欢迎指出,一起加油!!

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

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

相关文章

shell脚本——条件语句

目录 一、条件语句 1、test命令测试条件表达式 2、整数数值比较 3、字符串比较 4、逻辑测试&#xff08;短路运算&#xff09; 5、双中括号 二、if语句 1、 分支结构 1.1 单分支结果 1.2 双分支 1.3 多分支 2、case 一、条件语句 条件测试&#xff1a;判断某需求是…

【HarmonyOS应用开发】UIAbility实践第二部分(六)

内容接上篇 【HarmonyOS应用开发】UIAbility实践第一部分&#xff08;五&#xff09; 末尾含示例源码 三、UIAbility的生命周期 当用户浏览、切换和返回到对应应用的时候&#xff0c;应用中的UIAbility实例会在其生命周期的不同状态之间转换。 UIAbility类提供了很多回调&a…

[C语言][C++][时间复杂度详解分析]二分查找——杨氏矩阵查找数字详解!!!

一&#xff0c;题目 遇到的一道算法题&#xff1a; 1&#xff0c;已知有一个数字矩阵&#xff08;row行&#xff0c;col列&#xff09;&#xff0c;矩阵的每行 从左到右 递增&#xff0c;每列 从上到下 递增。 2&#xff0c;现输入一个数字 num &#xff0c;判断数字矩阵中…

玩转WEB接口之三续篇【HTTPS证书申请 - nginx验证】

文章目录 一&#xff0c; 概述二&#xff0c;nginx下载三&#xff0c;访问域名1. 做域名映射2. 运行nginx并通过域名访问 四&#xff0c;配置SSL证书1. 配置证书文件2. nginx 添加证书文件 五、运行并验证1. 测试、重新加载2. https访问 一&#xff0c; 概述 接上篇 玩转WEB接…

深度强化学习(王树森)笔记06

深度强化学习&#xff08;DRL&#xff09; 本文是学习笔记&#xff0c;如有侵权&#xff0c;请联系删除。本文在ChatGPT辅助下完成。 参考链接 Deep Reinforcement Learning官方链接&#xff1a;https://github.com/wangshusen/DRL 源代码链接&#xff1a;https://github.c…

在Java中如何优雅使用正则表达式?

在Java中如何优雅使用正则表达式&#xff1f; 一、正则表达式的基本概念与用途 1.1 正则表达式的简介 正则表达式&#xff0c;又称规则表达式。&#xff08;英语&#xff1a;Regular Expression&#xff0c;在代码中常简写为regex、regexp或RE&#xff09;&#xff0c;是计算…

SpringBoot引入主盘探活定时任务

主盘探活通常是指检查存储设备&#xff08;例如硬盘&#xff09;是否可读写&#xff0c;但在Java中并没有直接针对硬件级别的磁盘探活API。然而&#xff0c;我们可以模拟一个场景&#xff0c;即检查某个目录或文件是否可以被Java程序正常读写&#xff0c;以此作为主盘活跃的一个…

网络防御安全知识(第三版)

配置黑洞路由 --- 黑洞路由即空接口路由&#xff0c;在NAT地址池中的地址&#xff0c;建议配置达到这个地址指 向空接口的路由&#xff0c;不然&#xff0c;在特定环境下会出现环路。&#xff08;主要针对地址池中的地址和出接口地址 不再同一个网段中的场景。&#xff09; …

Log4j2的Appenders配置详解

官方配置文档 https://logging.apache.org/log4j/2.x/manual/appenders.html#RollingFileAppender <Appenders> 常使用的类如下&#xff1a; org.apache.log4j.ConsoleAppender&#xff08;控制台&#xff09; org.apache.log4j.FileAppender&#xff08;文件&#xff…

vue3-深入组件-透传属性

透传属性 &#xff08;透传 attribute&#xff09; 什么是透传属性&#xff08;透传 attribute&#xff09;? 传递给一个组件&#xff0c;却没有被该组件声明为 props 或 emits 的 attribute 或者是事件监听器&#xff0c;例如 class style id 等。 属性继承 当一个组件以单…

如何搭建开源笔记Joplin服务并实现远程访问本地数据

文章目录 1. 安装Docker2. 自建Joplin服务器3. 搭建Joplin Sever4. 安装cpolar内网穿透5. 创建远程连接的固定公网地址 Joplin 是一个开源的笔记工具&#xff0c;拥有 Windows/macOS/Linux/iOS/Android/Terminal 版本的客户端。多端同步功能是笔记工具最重要的功能&#xff0c;…

类和对象(2)之类的6个默认成员函数(2)

上次我们梳理了初始化和清理的知识点&#xff0c;今天我们要梳理的是拷贝赋值的知识点。 拷贝构造函数 看到拷贝构造函数这个名字就能看的出来它是一个构造函数&#xff0c;所以它的语法和构造函数很相似。 既然他是一个构造函数&#xff0c;那么他就具有构造函数的语法&…