走迷宫----bfs再矩阵图里的应用模版

对于之前走迷宫的那个题

回忆一下dfs的代码

#include <bits/stdc++.h>
using namespace std;
int a[110][110];
bool check[110][110];
int n,m;
int ans=1e9;
int nxt[4][2]={{1,0},{0,-1},{-1,0},{0,1}};
void dfs(int x,int y,int step){if(x==n&&y==m){ans=min(ans,step);return;}for(int i=0;i<4;i++){int nx=x+nxt[i][0];int ny=y+nxt[i][1];if(check[nx][ny]==1||nx<1||nx>n||ny<1||ny>m||check[nx][ny]==true){continue;}else{check[nx][ny]=true;dfs(nx,ny,step+1);check[nx][ny]=false;}}}
int main(){cin>>n>>m;for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){cin>>a[i][j];}}check[1][1]=true;dfs(1,1,0);cout<<ans;
}

我们是用dfs解决的,当时只是为了练习dfs的思想和熟练度,但一但地图大,方案变多,dfs就会超时。一个20*20的矩阵dfs能跑几十分钟,原因就是在dfs的回溯上,dfs算法里每个点会被遍历多次,这大大浪费了我们的时间 。

这道题的正解应该是用bfs来做,bfs时间短的原因就在于它每个点只遍历一次(还不一定遍历所有点,到目标点他就跳出循环了)。

bfs的算法我们是用队列这一数据结构实现的,为什么要用队列呢,这和这个算法的核心思想密切相关,bfs的核心就在于对当前能走到的所有点进行扩展,然后再对第一次扩展到的点找到它所能到达的所有点进行扩展,不断从起点扩展这个图直到扩展到终点。注意,在扩展完当前点能走到的所有点以后这个点就可以不要了,我们始终保留站在地图最前沿的那一批开拓者,看开拓者的位置是否为终点即可(因为一个点只要进行开拓操作,那它就一定不是终点,否则直接跳出循环就不去开拓了),不断开拓直到找到终点

这里推荐一个b站的视频模拟该过程模拟的非常好:BFS广搜解决迷宫问题_哔哩哔哩_bilibili

代码也没用到晦涩难懂的二元组之类的,很简单的结构体队列

我们结合这道题对bfs进行讲解,注释写的很明白(自认为)

#include <bits/stdc++.h>
using namespace std;
const int N=110;
int a[N][N];//存储地图数据
int n,m;//读入行数,列数
bool check[N][N];//防止往回走的check数组
struct point{/*结构体存储开拓者的坐标和这是第几次开拓到达的点(见过用二元组写的但是感觉结构体更好看懂)*/int x;int y;int step;
};
queue<point> aa;//定义结构体队列
int nex[4][2]={{1,0},{0,-1},{-1,0},{0,1}};//往右,下,左,上四个方向走的情况
int flag;//记录终点到达不了的情况
void bfs(){while(!aa.empty()){//队列非空就还能开拓,队列空了还没找到答案就是没有通往终点的路point t=aa.front();//取出队头元素对他进行扩展(用t承接着方便操作)if(t.x==n&&t.y==m){//找到终点了flag=1;cout<<t.step;return;}for(int i=0;i<4;i++){//分别尝试向四个方向扩展int nx=t.x+nex[i][0];int ny=t.y+nex[i][1];if(check[nx][ny]==true||a[nx][ny]==1||nx<1||nx>n||ny<1||ny>m){/*排除一切不符合情况的走法:走回头路,超出边界,撞到障碍物*/continue; }else{ //满足扩展条件,入队point temp;//用个临时结构体承接一下要入队的数据(将数据规范整合成结构体的形式再塞入队列中)temp.x=nx,temp.y=ny,temp.step=t.step+1;aa.push(temp);check[nx][ny]=true;}}//扩展完当前队头能走的所有点后队头元素没用了(用过了),出队aa.pop();}if(flag==0) cout<<-1;
}
int main(){cin>>n>>m;for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){cin>>a[i][j];}}
//初始化队列point start;start.x=1;start.y=1;start.step=0;aa.push(start);check[1][1]=true;bfs();
}

最后不得不再次感叹不同数据结构的强大 

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

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

相关文章

IntelliJ IDEA集成git配置账号密码

1 背景说明 刚使用IDEA,本地也安装Git,在提交和拉取代码的时候,总提示登录框,而且登录框还不能输入账号密码,只能输入登录Token。如下: 从而无法正常使用IDEA的Git功能,很苦恼。 2 解决方法 2.1 安装Git 进入官网地址 https://git-scm.com/,点击下载: 浏览器直接…

机器学习算法那些事 | 使用Transformer模型进行时间序列预测实战

本文来源公众号“机器学习算法那些事”&#xff0c;仅用于学术分享&#xff0c;侵权删&#xff0c;干货满满。 原文链接&#xff1a;使用Transformer模型进行时间序列预测实战 时间序列预测是一个经久不衰的主题&#xff0c;受自然语言处理领域的成功启发&#xff0c;transfo…

WPS制作甘特图

“ 甘特图&#xff08;Gantt chart&#xff09;又称为横道图、条状图&#xff08;Bar chart&#xff09;&#xff0c;通过条状图来显示项目、进度和其他时间相关的系统进展的内在关系随着时间进展的情况。” 设置基础样式 设置行高 设置宽度 准备基础数据 计算持续时间 …

轻松引流几百精准粉丝,抖音自动爆粉秘籍揭秘

对于做互联网的朋友们来说&#xff0c;引流是一个必不可少的环节。 掌握一种优秀的引流方法至关重要&#xff0c;这也可以视为我们的生计之源。 今天&#xff0c;我将向大家介绍一款全自动的引流工具——抖音全自动引流脚本软件。 这款软件的效果非常显著&#xff0c;它可以替…

R-CNN笔记

目标检测之R-CNN论文精讲&#xff0c;RCNN_哔哩哔哩_bilibili 论文背景 在该论文提出之前&#xff0c;主流的目标检测思路是&#xff1a; 将一幅图片划分成很多个区域&#xff0c;单独提取出来 对于每个区域使用传统的特征提取方法提取 提取结束后可以使用以为特征向量表示 可以…

计算方法实验2:列主元消元法和Gauss-Seidel迭代法解线性方程组

Task 即已知 y 0 0 , y 100 1 y_00,y_{100}1 y0​0,y100​1&#xff0c;解线性方程组 A y b \mathbf{A}\mathbf{y} \mathbf{b} Ayb&#xff0c;其中 A 99 99 [ − ( 2 ϵ h ) ϵ h 0 ⋯ 0 ϵ − ( 2 ϵ h ) ϵ h ⋯ 0 0 ϵ − ( 2 ϵ h ) ⋯ 0 ⋮ ⋮ ⋱ ⋱ ⋮ 0 0 ⋯…

C++命名空间和内联函数

目录 命名空间 内联函数 概述 特性&#xff1a; 命名空间 在C/C中&#xff0c;变量&#xff0c;函数和和类这些名称都存在于全局作用域中&#xff0c;可能会导致很多冲突&#xff0c;使用命名空间的目的是对标识符的名称进行本地化&#xff0c;避免命名冲突或名字污染&…

C语言函数和数组

目录 一.数组 一.一维数组&#xff1a; 1.一维数组的创建: 2.一维数组的初始化&#xff1a; 3.一维数组的使用 4.一维数组在内存中的存储&#xff1a; 二.二维数组&#xff1a; 三.数组越界&#xff1a; 四.数组作为函数参数&#xff1a; 二.函数 一.函数是什么&…

vue3对openlayers使用(加高德,天地图图层)

OpenLayers认识 WebGIS四大框架&#xff1a; Leaflet、OpenLayers、Mapbox、Cesium OpenLayers 是一个强大的开源 JavaScript 地图库&#xff0c;专注于提供可嵌入网页的交互式地图体验。作为一款地理信息系统&#xff08;GIS&#xff09;的前端开发工具&#xff0c;OpenLaye…

关于php foreach函数和变量覆盖

foreach函数是PHP中用于遍历数组或对象的函数&#xff08;且仅用于数组的遍历&#xff09;。它允许循环遍历数组中的每个元素&#xff0c;并对每个元素执行相同的操作。foreach语句的基本语法如下&#xff1a; foreach ($array as $value) {//执行的操作 }在这个语法中&#x…

C++ Thread 源码 观后 自我感悟 整理

Thread的主要数据成员为_Thr 里面存储的是线程句柄和线程ID 先看看赋值运算符的移动构造 最开始判断线程的ID是否不为0 _STD就是使用std的域 如果线程ID不为0&#xff0c;那么就抛出异常 这里_New_val使用了完美转发&#xff0c;交换_Val和_New_val的值 _Thr _STD exchange(_…

回归预测 | Matlab基于SAO-LSTM雪消融算法优化长短期记忆神经网络的数据多输入单输出回归预测

回归预测 | Matlab基于SAO-LSTM雪消融算法优化长短期记忆神经网络的数据多输入单输出回归预测 目录 回归预测 | Matlab基于SAO-LSTM雪消融算法优化长短期记忆神经网络的数据多输入单输出回归预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab基于SAO-LSTM雪消融…

【Linux】进程的进一步认识

目录 进程的创建 fork函数初步认识 fork函数的返回值 写时拷贝 操作系统怎么知道什么时候要写时拷贝的呢&#xff1f; fork的常规用法 fork调用失败的原因 进程终止 进程的退出场景 进程常见退出方法 正常终止&#xff08;可以通过 echo $? 查看进程退出码&#xff…

Spring Boot从入门到实战

课程介绍 本课程从SpringBoot的最基础的安装、配置开始到SpringBoot的日志管理、Web业务开发、数据存储、数据缓存&#xff0c;安全控制及相关企业级应用&#xff0c;全程案例贯穿&#xff0c;案例每一步的都会讲解实现思路&#xff0c;全程手敲代码实现。让你不仅能够掌Sprin…

【Linux操作系统】:进程控制

目录 一、程序地址空间 1.C/C中的程序地址空间 2.进程地址空间 进程地址空间概念 什么是地址空间&#xff1f;什么是区域划分&#xff1f; 为啥要有地址空间&#xff1f; 地址空间的补充 二、进程创建 1.fork函数 2.写时拷贝 3.fork常规用法 4.fork调用失败的原因 …

Linux 常用命令 1

Tips&#xff1a;终端热键ctrl shift 放大终端窗口的字体 ctrl - 缩小终端窗口的字体 注意区分大小写 查阅命令帮助信息&#xff1a; 1&#xff09;--help command –help(两个减号) 显示command命令的帮助信息 2&#xff09;man man command 查阅command命令的使…

MyEclipse打开文件跳转到notepad打开问题

问题描述 windows系统打开README.md文件&#xff0c;每次都需要右键选择notepad打开&#xff0c;感觉很麻烦&#xff0c;然后就把README.md文件打开方式默认选择了notepad&#xff0c;这样每次双击就能打开&#xff0c;感觉很方便。 然后某天使用MyEclipse时&#xff0c;双击RE…

matlab实现神经网络检测手写数字

一、要求 1.计算sigmoid函数的梯度&#xff1b; 2&#xff0e;随机初始化网络权重&#xff1b; 3.编写网络的代价函数。 二、算法介绍 神经网络结构&#xff1a; 不正则化的神经网络的代价函数&#xff1a; 正则化&#xff1a; S型函数求导&#xff1a; 反向传播算法&…

【Linux】Linux工具学习之git

&#x1f525;博客主页&#xff1a; 小羊失眠啦. &#x1f3a5;系列专栏&#xff1a;《C语言》 《数据结构》 《C》 《Linux》 《Cpolar》 ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 文章目录 前言一、账号注册1.1 GitHub与Gitee 二、构建仓库三、安装git 四、配置git五、克…

详解库和程序运行过程

我最近开了几个专栏&#xff0c;诚信互三&#xff01; > |||《算法专栏》&#xff1a;&#xff1a;刷题教程来自网站《代码随想录》。||| > |||《C专栏》&#xff1a;&#xff1a;记录我学习C的经历&#xff0c;看完你一定会有收获。||| > |||《Linux专栏》&#xff1…