[C/C++] -- 搜索迷宫路径

DFS(深度优先搜索)和BFS(广度优先搜索)是两种常用的图遍历算法,它们在搜索图或树中的节点时有着不同的策略和特点。

  1. 深度优先搜索 (DFS):

    • 在DFS中,从起始节点开始,沿着一条路径尽可能深地搜索,直到到达叶子节点或者无法继续搜索为止,然后回溯到上一个节点,选择另一条路径继续搜索,直到所有节点都被访问。
    • DFS通常使用递归或者来实现,递归是自然而直观的实现方式,而使用栈可以避免递归的潜在问题(如栈溢出)。
    • DFS的优点是在搜索过程中不需要记录所有访问过的节点,因此占用的空间较少。
    • 适用于寻找深度路径,比如解决迷宫问题、寻找图的连通分量等。
  2. 广度优先搜索 (BFS):

    • 在BFS中,从起始节点开始,首先访问起始节点的所有邻居节点,然后依次访问这些邻居节点的邻居节点,以此类推,直到所有节点都被访问。
    • BFS通常使用队列来实现,保证了节点的访问顺序是按照距离起始节点的距离逐层递增的。
    • BFS的优点是可以找到起始节点到目标节点的最短路径,而且在无权图中具有最优性(即找到的第一个解就是最短路径)。
    • 适用于寻找最短路径,比如在迷宫中找到最短路径、在社交网络中找到两个人之间的最短关系链等。

1.深度优先遍历DFS

设计一个程序,能够对给定的迷宫进行路径搜索,并输出一条从起点到终点的路径。具体来说,程序需要实现以下功能:

  1. 接受用户输入的迷宫地图,包括迷宫的行数和列数,以及每个格子的状态(0 表示可通行,1 表示不可通行)。
  2. 使用深度优先搜索算法(DFS)对迷宫进行搜索,找到从起点到终点的一条路径。
  3. 输出搜索到的路径。

入栈以后,然后我们查看栈顶元素,是(0,0)这个节点。栈现在不为空,取栈顶元素,先看它右边能不能走,能走的话,就一直向右走,它右边是0,就入栈了。

_pMaze[0][0]._val == 1return;
_stack. Push(_pMaze[0][0]);//左上角节点入栈 
while (!_stack. Empty())//栈不为空 Node top = _stack. Top();

 如果栈顶元素的右边可以走的话,我们要把当前节点的右方向改成不能走,把右边节点的左方向改成不能走。因为不能走回头路,而且因为路子走不通回退后也不能继续走相同的死路。

//往右方向寻找if (_pMaze[x][y]._state[RIGHT] == YES){_pMaze[x][y]._state[RIGHT] = NO;_pMaze[x][y + 1]._state[LEFT] = NO;_stack.push(_pMaze[x][y + 1]);continue;

深度遍历入栈后,不用判断之前节点的方向。continue后,重新取栈顶元素,继续进行判断。同理,如果右边不能走,下边可以走的话:

//往下方向寻找if (_pMaze[x][y]._state[DOWN] == YES){_pMaze[x][y]._state[DOWN] = NO;_pMaze[x + 1][y]._state[UP] = NO;_stack.push(_pMaze[x + 1][y]);continue;}

 同理:左方向

//往左方向寻找if (_pMaze[x][y]._state[LEFT] == YES){_pMaze[x][y]._state[LEFT] = NO;_pMaze[x][y - 1]._state[RIGHT] = NO;_stack.push(_pMaze[x][y - 1]);continue;}

如果栈顶元素判断完四个方向都不能走,就是到死路了,就把栈顶元素出栈。
然后再取栈顶元素,进行判断,如果它的4个方向都不能走,就出栈,如果栈为空,则迷宫无通路。如果有方向能走,就继续走下去。以此类推下去。但是,都要判断一下此节点是不是右下角的节点,如果是,就是找到通路了。

//已经找到右下角出口得迷宫路径if (x == _row - 1 && y == _col - 1){return;}

 完整代码:

#include <iostream>
#include <stack>
using namespace std;//定义迷宫每一个节点的四个方向
const int RIGHT = 0;//右 
const int DOWN = 1;//下 
const int LEFT = 2;//左 
const int UP = 3;//上 //迷宫每一个节点方向的数量
const int WAY_NUM = 4;//定义节点行走状态
const int YES = 4;//当前方向可以走 
const int NO = 5;//当前方向不能走 //迷宫
class Maze
{
public://初始化迷宫,根据用户输入的行列数,生成存储迷宫路径信息的二维数组Maze(int row, int col):_row(row), _col(col){_pMaze = new Node*[_row];//注意元素类型是Node for (int i = 0; i < _row; ++i){_pMaze[i] = new Node[_col];}}//初始化迷宫路径节点信息void initNode(int x, int y, int val){_pMaze[x][y]._x = x;_pMaze[x][y]._y = y;_pMaze[x][y]._val = val;//节点四个方向默认的初始化都为不能走 for (int i = 0; i < WAY_NUM; ++i){_pMaze[x][y]._state[i] = NO;}}//初始化迷宫0节点四个方向的行走状态信息 当前节点右下左上,如果是0,改成可以走 void setNodeState(){for (int i = 0; i < _row; ++i){for (int j = 0; j < _col; ++j){if (_pMaze[i][j]._val == 1){continue;//不用调整了,因为走不到值为1的节点 }//j不能取到最后一列,不然就判断越界了 if (j < _col - 1 && _pMaze[i][j + 1]._val == 0)//逻辑&,是先计算左边的表达式,左边如果是false,右边就不用计算了 {_pMaze[i][j]._state[RIGHT] = YES;}if (i < _row - 1 && _pMaze[i + 1][j]._val == 0){_pMaze[i][j]._state[DOWN] = YES;}//j不用取第一类,因为本身就不能走 if (j > 0 && _pMaze[i][j - 1]._val == 0){_pMaze[i][j]._state[LEFT] = YES;}if (i > 0 && _pMaze[i - 1][j]._val == 0){_pMaze[i][j]._state[UP] = YES;}}}}//深度搜索迷宫路径void searchMazePath(){if (_pMaze[0][0]._val == 1){return;}_stack.push(_pMaze[0][0]);//左上角节点入栈 while (!_stack.empty())//栈不为空 {Node top = _stack.top();int x = top._x;int y = top._y;//已经找到右下角出口得迷宫路径if (x == _row - 1 && y == _col - 1){return;}//往右方向寻找if (_pMaze[x][y]._state[RIGHT] == YES){_pMaze[x][y]._state[RIGHT] = NO;_pMaze[x][y + 1]._state[LEFT] = NO;_stack.push(_pMaze[x][y + 1]);continue;}//往下方向寻找if (_pMaze[x][y]._state[DOWN] == YES){_pMaze[x][y]._state[DOWN] = NO;_pMaze[x + 1][y]._state[UP] = NO;_stack.push(_pMaze[x + 1][y]);continue;}//往左方向寻找if (_pMaze[x][y]._state[LEFT] == YES){_pMaze[x][y]._state[LEFT] = NO;_pMaze[x][y - 1]._state[RIGHT] = NO;_stack.push(_pMaze[x][y - 1]);continue;}//往上方向寻找if (_pMaze[x][y]._state[UP] == YES){_pMaze[x][y]._state[UP] = NO;_pMaze[x - 1][y]._state[DOWN] = NO;_stack.push(_pMaze[x - 1][y]);continue;}_stack.pop();}}//打印迷宫路径搜索结果void showMazePath(){if (_stack.empty()){cout << "不存在一条迷宫路径!" << endl;}else{while (!_stack.empty())//栈不为空,取出节点坐标,相应值调整为* {Node top = _stack.top();_pMaze[top._x][top._y]._val = '*';_stack.pop();}for (int i = 0; i < _row; ++i)//打印迷宫{for (int j = 0; j < _col; ++j){if (_pMaze[i][j]._val == '*'){cout << "* ";}else{cout << _pMaze[i][j]._val << " ";}}cout << endl;}}}
private://定义迷宫节点路径信息struct Node{int _x;//节点的横坐标 int _y;//节点的纵坐标 int _val;//节点的值int _state[WAY_NUM];//记录节点四个方向的状态(左右上下)//4个元素位置(左右上下),存储yes或者no };Node **_pMaze;//动态生成迷宫路径(动态开辟二维数组) int _row;//迷宫的行 int _col;//迷宫的列 stack<Node> _stack;//栈结构,辅助深度搜索迷宫路径
};int main()
{cout << "请输入迷宫的行列数(例如:10 10):";int row, col, data;cin >> row >> col;Maze maze(row, col);//创建迷宫对象cout << "请输入迷宫的路径信息(0表示可以走,1表示不能走):" << endl;for (int i = 0; i < row; ++i)//只能获取i,j和data值,节点的4个方向的行走状态还不能初始化 {for (int j = 0; j < col; ++j){cin >> data;//可以初始化迷宫节点的基本信息maze.initNode(i, j, data);}}//开始设置所有节点的四个方向的状态maze.setNodeState();//开始从左上角搜索迷宫的路径信息了maze.searchMazePath();//打印迷宫路径搜索的结果maze.showMazePath();return 0;
}

 

 2.广度优先遍历BFS

#include <iostream>
#include <queue>
#include <vector>
using namespace std;//定义方向
const int RIGHT = 0;
const int DOWN = 1;
const int LEFT = 2;
const int UP = 3;
const int WAY_NUM = 4;//定义行走状态
const int YES = 4;
const int NO = 5;//迷宫
class Maze
{
public:Maze(int row, int col):_row(row), _col(col){_pMaze = new Node*[_row];//开辟迷宫二维数组 for (int i = 0; i < _row; ++i){_pMaze[i] = new Node[_col];}//node._x*_row + node._y_pPath.resize(_row * _col);//辅助数组开辟空间 }void initNode(int x, int y, int val)//初始化为No {_pMaze[x][y]._x = x;_pMaze[x][y]._y = y;_pMaze[x][y]._val = val;for (int i = 0; i < WAY_NUM; ++i){_pMaze[x][y]._state[i] = NO;}}void setNodeState()//设置迷宫行走状态 {for (int i = 0; i < _row; ++i){for (int j = 0; j < _col; ++j){if (_pMaze[i][j]._val == 1){continue;}if (j < _col - 1 && _pMaze[i][j + 1]._val == 0){_pMaze[i][j]._state[RIGHT] = YES;}if (i < _row - 1 && _pMaze[i + 1][j]._val == 0){_pMaze[i][j]._state[DOWN] = YES;}if (j > 0 && _pMaze[i][j - 1]._val == 0){_pMaze[i][j]._state[LEFT] = YES;}if (i > 0 && _pMaze[i - 1][j]._val == 0){_pMaze[i][j]._state[UP] = YES;}}}}void searchMazePath()//广度优先遍历搜索 {if (_pMaze[0][0]._val == 1){return;}_queue.push(_pMaze[0][0]);//入口节点入队 while (!_queue.empty())//队列不为空 {Node front = _queue.front();//获取队头元素 int x = front._x;int y = front._y;//右方向if (_pMaze[x][y]._state[RIGHT] == YES){_pMaze[x][y]._state[RIGHT] = NO;_pMaze[x][y + 1]._state[LEFT] = NO;//在辅助数组中记录一下节点的行走信息_pPath[x*_row + y + 1] = _pMaze[x][y];_queue.push(_pMaze[x][y + 1]);if (check(_pMaze[x][y + 1]))return;}//下方向if (_pMaze[x][y]._state[DOWN] == YES){_pMaze[x][y]._state[DOWN] = NO;_pMaze[x + 1][y]._state[UP] = NO;_pPath[(x + 1)*_row + y] = _pMaze[x][y];_queue.push(_pMaze[x + 1][y]);if (check(_pMaze[x + 1][y]))return;}//左方向if (_pMaze[x][y]._state[LEFT] == YES){_pMaze[x][y]._state[LEFT] = NO;_pMaze[x][y - 1]._state[RIGHT] = NO;_pPath[x*_row + y - 1] = _pMaze[x][y];_queue.push(_pMaze[x][y - 1]);if (check(_pMaze[x][y - 1]))return;}//上方向if (_pMaze[x][y]._state[UP] == YES){_pMaze[x][y]._state[UP] = NO;_pMaze[x - 1][y]._state[DOWN] = NO;_pPath[(x - 1)*_row + y] = _pMaze[x][y];_queue.push(_pMaze[x - 1][y]);if (check(_pMaze[x - 1][y]))return;}//当前节点出队列_queue.pop();}}void showMazePath()//打印迷宫 {if (_queue.empty()){cout << "不存在一条迷宫路径!" << endl;}else{//回溯寻找迷宫路径节点int x = _row - 1;int y = _col - 1;for (;;){_pMaze[x][y]._val = '*';if (x == 0 && y == 0)break;Node node = _pPath[x*_row + y];x = node._x;y = node._y;}for (int i = 0; i < _row; ++i){for (int j = 0; j < _col; ++j){if (_pMaze[i][j]._val == '*'){cout << "* ";}else{cout << _pMaze[i][j]._val << " ";}}cout << endl;}}}
private://定义迷宫节点路径信息struct Node{int _x;int _y;int _val;//节点的值int _state[WAY_NUM];//记录节点四个方向的状态};//检查是否是右下角的迷宫出口节点bool check(Node &node){return node._x == _row - 1 && node._y == _col - 1;}Node **_pMaze;//动态开辟二维数组 int _row;//行 int _col;//列 queue<Node> _queue;//广度遍历依赖的队列结构vector<Node> _pPath;//记录广度优先遍历时,节点的行走信息,辅助数组 
};int main()
{cout << "请输入迷宫的行列数(例如:10 10):";int row, col, data;cin >> row >> col;Maze maze(row, col);//创建迷宫对象cout << "请输入迷宫的路径信息(0表示可以走,1表示不能走):" << endl;for (int i = 0; i < row; ++i){for (int j = 0; j < col; ++j){cin >> data;//可以初始化迷宫节点的基本信息maze.initNode(i, j, data);}}//开始设置所有节点的四个方向的状态maze.setNodeState();//开始从左上角搜索迷宫的路径信息了maze.searchMazePath();//打印迷宫路径搜索的结果maze.showMazePath();return 0;
}

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

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

相关文章

健康知识集锦

页面 页面代码 <% layout(/layouts/default.html, {title: 健康知识管理, libs: [dataGrid]}){ %> <div class"main-content"><div class"box box-main"><div class"box-header"><div class"box-title"&g…

triton之语法学习

一 基本语法 1 torch中tensor的声明 x = torch.tensor([[1,2, 1, 1, 1, 1, 1, 1],[2,2,2,2,2,2,2,2]],device=cuda) 声明的时候有的时候需要指出数据的类型,不然在kernel中数据类型无法匹配 x = torch.tensor([1,2,1,1,1,1,1,1],dtype = torch.int32,device=cuda) 2 idx id…

2024年数据安全软件排行榜:哪款守护神最值得信赖?

在数字化时代&#xff0c;数据安全已成为企业和个人不可或缺的一部分。为了确保数字资产的安全&#xff0c;市场上涌现出了众多数据安全软件。以下是数据安全软件Top 10&#xff0c;它们以卓越的性能和功能&#xff0c;为您的数字世界提供坚实的保障。 一、数据安全系统排排行…

word-快速入门

1、熟悉word界面 2、word排版习惯 3、排版文本基本格式 1、word界面 选项卡 功能组 点击功能组右下角小三角可以开启完整功能组&#xff0c;获得启动器 软件右上角有功能显示折叠按钮 2、排版好习惯 &#xff08;1&#xff09;随时保存 &#xff08;2&#xff09;规范文件命…

替换spring-boot中的组件版本

spring-boot是一个用于简化开发的框架&#xff0c;引入spring-boot后会自动包含spring框架&#xff0c;通过引入xxx-start来完成指定组件的功能。比如&#xff1a; spring-boot-starter-web(嵌入 Tomcat 和 web 开发需要的 servlet 和 jsp 支持)spring-boot-starter-data-jpa(…

AI赋能EasyCVR视频汇聚/视频监控平台加快医院安防体系数字化转型升级

近来&#xff0c;云南镇雄一医院发生持刀伤人事件持续发酵&#xff0c;目前已造成2人死亡21人受伤。此类事件在医院层出不穷&#xff0c;有的是因为医患纠纷、有的是因为打架斗殴。而且在每日大量流动的人口中&#xff0c;一些不法分子也将罪恶的手伸到了医院&#xff0c;实行扒…

使用golang实现k-means

k-means聚类算法 K-Means是一种无监督算法&#xff0c;其目标是将数据进行分类。分类个数要求已知。 k-means流程 随机确定K个点作为质心、找到离每个点最近的质心&#xff0c;将这个点分配到这个质心代表的簇里再对每个簇进行计算&#xff0c;以点簇的均值点作为新的质心如…

LeetCode343:整数拆分

题目描述 给定一个正整数 n &#xff0c;将其拆分为 k 个 正整数 的和&#xff08; k > 2 &#xff09;&#xff0c;并使这些整数的乘积最大化。 返回 你可以获得的最大乘积 。 代码 动态规划 class Solution { public:int integerBreak(int n) {/*dp[i]&#xff1a;表示对…

vue3组件插槽

Index.vue: <script setup> import { ref, onMounted } from vue import Child from ./Child.vue import ./index.cssonMounted(() > {}) </script><template><div class"m-home-wrap"><Child>插槽</Child><div class&qu…

使用flutter开发一个U盘文件管理APP,只解析图片文件

今天教大家用flutter撸一个U盘文件管理APP,需求是这样的: 当我在Android设备上插入U盘后,我能在APP中打开U盘的文件目录,并且能进入对应目录的下一级目录,如果下级目录下有图片文件,我就对这个图片文件进行解析,并展示出来。 需求了解后,先上个效果图: 效果图看完后,…

【Java orm 框架比较】九 新增wood框架对比

【Java orm 框架比较】九 新增wood框架对比 本次新增wood 框架测试 测试数据存储、分页查询&#xff0c;文档及框架比较稳定半天时间加入测试使用 迁移到&#xff08;https://gitee.com/wujiawei1207537021/spring-orm-integration-compare&#xff09; orm框架使用性能比较…

Java设计模式 _行为型模式_命令模式

一、命令模式 1、命令模式 命令模式&#xff08;Command Pattern&#xff09;是一种行为型模式&#xff0c;一种数据驱动的设计模式。命令模式中请求以命令的形式包裹在对象中&#xff0c;即将命令封装为类&#xff0c;从而可以使用不同的请求&#xff0c;队列等操作具体的对象…

k8s部署最新版zookeeper集群(3.9.2),并配置prometheus监控

目录 zookeeper集群部署创建zookeeper文件夹namespace.yamlscripts-configmap.yamlserviceaccount.yamlstatefulset.yamlsvc-headless.yamlsvc.yamlmetrics-svc.yaml执行部署 接入prometheus访问prometheus查看接入情况导入zookeeper监控模版监控展示 zookeeper集群部署 复制粘…

【数据结构】 二叉树的顺序结构——堆的实现

普通的二叉树是不适合用数组来存储的&#xff0c;因为可能会存在大量的空间浪费。而完全二叉树更适合使用顺序结构存储。现实中我们通常把堆(一种二叉树)使用顺序结构的数组来存储 。 一、堆的概念及结构 父节点比孩子结点大 是大堆 父节点比孩子结点小 是小堆 堆的性质 堆中某…

Centos7使用kubeadm搭建k8s集群(一主两从)----(mac版)

一、环境准备 1、下载centos7镜像 阿里巴巴开源镜像站-OPSX镜像站-阿里云开发者社区 下载地址: centos安装包下载_开源镜像站-阿里云 选择对应的版本即可&#xff0c;我下载的&#xff1a;CentOS-7-x86_64-DVD-2207-02.iso 2、使用VirtualBox安装centos 选择新建&#xff0c…

Mac下安装ffmpeg

1、安装gedit brew install gedit2、配置环境变量&#xff0c;打开~/.zshrc&#xff0c;在末尾添加语句 export PATH$PATH:/usr/local/ffmpeg/bin3、执行语句&#xff0c;使环境变量生效 source ~/.zshrc 4、终端输入 ffmpeg &#xff0c;看环境变量是否配置成功。 至此&a…

现货黄金流程到何种程度?现货黄金在金融产品中的占比是多少?

踏入2024年以来&#xff0c;受美联储降息以及地缘局势紧张的影响&#xff0c;美元受压&#xff0c;避险情绪高涨&#xff0c;众多因素影响下黄金价格出现了强势的上涨&#xff0c;屡创历史新高。在上涨如此强劲的背景下&#xff0c;投资者希望通过黄金投资来实现资产增值。市场…

C++语法|进程虚拟地址空间和函数调用栈

本文来自施磊老师的课程&#xff0c;老师讲的非常不错&#xff0c;我的笔记也是囫囵吞枣全部记下&#xff0c;但是我在这里推荐一本书&#xff0c;真的真的建议初学C或者想要进阶C的同学们看看&#xff1a;《CPU眼里的C/C》 文章目录 进程的虚拟地址空间和布局进程虚拟地址空间…

ros 学习记录(二)URDF小车运动控制

URDF小车运动控制 准备工作创建 robot_xacro.launch 接上文&#xff0c;想用键盘控制小车在Gazebo中移动。 准备工作 名称版本ROSNoeticGazebo11.11.0 创建 robot_xacro.launch 通过运行这个launch文件&#xff0c;可以启动Gazebo仿真环境&#xff0c;并在仿真环境中加载和…

【八十五】【算法分析与设计】单调栈的全新版本,两个循环维护左小于和右小于信息,84. 柱状图中最大的矩形,85. 最大矩形

84. 柱状图中最大的矩形 给定 n 个非负整数&#xff0c;用来表示柱状图中各个柱子的高度。每个柱子彼此相邻&#xff0c;且宽度为 1 。 求在该柱状图中&#xff0c;能够勾勒出来的矩形的最大面积。 示例 1: 输入&#xff1a;heights [2,1,5,6,2,3] 输出&#xff1a;10 解释&am…