BFS广度优先搜索和DFS深度优先搜索解决迷宫问题

news2024/11/24 17:57:20

前言

BFS广度优先搜索和DFS深度优先搜索解决迷宫问题


迷宫问题

原题目:迷宫由n行m列的单元格组成(n,m都小于等于50),每个单元格要吗是空地要吗是障碍物。现在请你找到一条从起点到终点的最短路径长度。
在这里插入图片描述

分析

BFS广度优先搜索

首先我们将起点入队,
然后队首节点可拓展的点入队,如果没有可拓展的点,将队首节点出队。重复该步骤直到达到目标位置或者队列为空。
在这里插入图片描述
DFS 深度优先搜索

在这里插入图片描述

代码如下:

BFS代码
#include <bits/stdc++.h>
using namespace std;

const int MAX = 100; // 定义最大矩阵大小
int a[MAX][MAX], v[MAX][MAX]; // a 用于存储迷宫地图,v 用于记录访问状态

// 定义点结构体
struct point {
    int x;    // 点的 x 坐标
    int y;    // 点的 y 坐标
    int step; // 从起点到达该点的步数
};

queue<point> r; // 申请队列,用于 BFS 遍历
int dx[4] = {0, 1, 0, -1}; // 四个方向的 x 偏移量(右、下、左、上)
int dy[4] = {1, 0, -1, 0}; // 四个方向的 y 偏移量(右、下、左、上)
/*
5 4
1 1 0 1
1 1 1 1
1 1 0 1
1 0 1 1
1 1 1 0
1 1 4 3
*/
int main() {
    int n, m; // 迷宫的行数和列数
    int startx, starty; // 起点的坐标
    int endx, endy; // 终点的坐标

    // 读取迷宫的行数和列数
    cin >> n >> m;
    
    // 初始化 v 数组,所有点的访问状态都设为 0(未访问)
    for(int i = 0; i < MAX; i++) {
        for(int j = 0; j < MAX; j++) {
            v[i][j] = 0;
        }
    }
    
    // 读取迷宫地图
    for(int i = 1; i <= n; i++) {
        for(int j = 1; j <= m; j++) {
            cin >> a[i][j];
        }
    }
    
    // 读取起点和终点的坐标
    cin >> startx >> starty >> endx >> endy;
    
    // 初始化 BFS 的起点
    point start;
    start.x = startx;
    start.y = starty;
    start.step = 0; // 起点的步数为 0
    r.push(start); // 将起点入队
    v[startx][starty] = 1; // 标记起点为已访问
    int flag = 0; // 标记是否找到路径

    // 开始 BFS 遍历
    while(!r.empty()) {
        int x = r.front().x; // 当前点的 x 坐标
        int y = r.front().y; // 当前点的 y 坐标
        int step = r.front().step; // 当前点的步数
        r.pop(); // 取出队首元素
        
        // 如果当前点是终点,输出步数并终止
        if(x == endx && y == endy) {
            flag = 1;
            cout << step << endl;
            break;
        }
        
        // 遍历四个方向
        for(int k = 0; k < 4; k++) {
            int tx = x + dx[k]; // 计算新点的 x 坐标
            int ty = y + dy[k]; // 计算新点的 y 坐标
            
            // 确保新点在合法范围内
            if(tx >= 1 && tx <= n && ty >= 1 && ty <= m) {
                // 如果新点是可通行的且未访问过
                if(a[tx][ty] == 1 && v[tx][ty] == 0) {
                    // 更新新点的坐标和步数
                    point temp;
                    temp.x = tx;
                    temp.y = ty;
                    temp.step = step + 1;
                    r.push(temp); // 将新点入队
                    v[tx][ty] = 1; // 标记新点为已访问
                }
            }
        }
    }
    
    // 如果没有找到路径,输出提示信息
    if(flag == 0) {
        cout << "没有路径" << endl;
    }
    
    return 0;
}
DFS代码
#include<bits/stdc++.h>
using namespace std;

int endx, endy;  // 终点的坐标
int a[100][100]; // 定义地图,1表示空地,0表示障碍物
int v[100][100]; // 访问标记数组,0表示未访问,1表示已访问
int minSteps = 99999999; // 初始化最小步数为一个较大的值,用于存储到达终点的最小步数

// 深度优先搜索 (DFS) 函数,x和y表示当前坐标,step表示当前走的步数
void dfs(int x, int y, int step) {
    // 如果当前坐标是终点
    if(x == endx && y == endy) {
        // 如果当前步数小于已知的最小步数,则更新最小步数
        if(step < minSteps) {
            minSteps = step;
        }
        return; // 返回,继续尝试其他路径
    }
    
    // 顺时针依次试探四个方向(右、下、左、上)

    // 右移动(坐标[x, y+1]),需要确保不越界且是空地且未访问过
    if(y + 1 <= 99 && a[x][y + 1] == 1 && v[x][y + 1] == 0) {
        v[x][y + 1] = 1;  // 标记该点为已访问
        dfs(x, y + 1, step + 1);  // 递归调用DFS,步数+1
        v[x][y + 1] = 0;  // 回溯,将该点标记为未访问,以便尝试其他路径
    }

    // 下移动(坐标[x+1, y]),需要确保不越界且是空地且未访问过
    if(x + 1 <= 99 && a[x + 1][y] == 1 && v[x + 1][y] == 0) {
        v[x + 1][y] = 1;  // 标记该点为已访问
        dfs(x + 1, y, step + 1);  // 递归调用DFS,步数+1
        v[x + 1][y] = 0;  // 回溯,将该点标记为未访问
    }

    // 左移动(坐标[x, y-1]),需要确保不越界且是空地且未访问过
    if(y - 1 >= 1 && a[x][y - 1] == 1 && v[x][y - 1] == 0) {
        v[x][y - 1] = 1;  // 标记该点为已访问
        dfs(x, y - 1, step + 1);  // 递归调用DFS,步数+1
        v[x][y - 1] = 0;  // 回溯,将该点标记为未访问
    }

    // 上移动(坐标[x-1, y]),需要确保不越界且是空地且未访问过
    if(x - 1 >= 1 && a[x - 1][y] == 1 && v[x - 1][y] == 0) {
        v[x - 1][y] = 1;  // 标记该点为已访问
        dfs(x - 1, y, step + 1);  // 递归调用DFS,步数+1
        v[x - 1][y] = 0;  // 回溯,将该点标记为未访问
    }
    return;  // 返回,继续试探其他路径
} 

int main() {
    int startx, starty, m, n;  // 起点坐标startx, starty,m表示行数,n表示列数
    cin >> m >> n;  // 输入地图的大小,m行n列
    
    // 输入地图信息,1表示空地,0表示障碍物
    for(int i = 1; i <= m; i++) {
        for(int j = 1; j <= n; j++) {
            cin >> a[i][j]; // 输入每个位置的地形,1为空地,0为障碍
        } 
    }
    
    // 输入起点坐标和终点坐标
    cin >> startx >> starty >> endx >> endy;
    
    // 初始化起点,将起点标记为已访问
    v[startx][starty] = 1;
    // 调用DFS从起点开始搜索,初始步数为0
    dfs(startx, starty, 0);
    
    // 如果最终没有找到到达终点的路径,输出-1
    if(minSteps == 99999999) {
        cout << -1 << endl; // 无法到达终点
    } else {
        // 输出最小步数
        cout << minSteps << endl;
    }
    
    return 0;
}

BFS和DFS的区别

广度优先搜索:

将队首结点可以拓展的点入队,如果没有可以拓展的点,将队首结点出队。重复上述步骤,直到到达目标位置或者队列为空。BFS搜索到的结果一定是最短的。BFS运用到了队列。

深度优先搜索:

(从某点出发,沿着一个方向往下试探,当找到目标位置,还需回溯,以便找到所有的路径,再比较最短的路径,比较盲目,效率没有BFS高。DFS运用到了栈。

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

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

相关文章

iOS 18 RC 版本更新,为相机应用引入了“暂停录制视频”功能

苹果公司9月10日正式向全球iPhone用户推送了iOS 18 Release Candidate&#xff08;RC&#xff09;版本。这一版本的发布不仅标志着iOS系统的又一次重大更新&#xff0c;更预示着苹果在提升用户体验、增强隐私保护以及推动AI应用方面的持续努力。 并且此次苹果公司最新推出的 i…

Unity基本操作

API手册 Unity 脚本 APIhttps://docs.unity.cn/cn/2022.3/ScriptReference/index.html 在遇到不懂的方法、想更深入的学习或者是想查看是否有相应的方法实现某项功能&#xff0c;可以在Unity官方这里查看脚本。以Transform为例&#xff0c;可以直接搜索&#xff0c;或者在Unit…

9月12日 QT

//设置图片缩放适应label ui->label->setScaledContents(true); // 在spinbox后方设置$特殊符号 ui->spinBox->setSuffix(" 斤"); //给肉类combobox加入项目 QStringList Meat_List{"请选择&quo…

数据放到GPU上,运行程序卡住检查方法

这个问题一定是要结合具体的代码&#xff0c;下面就自己遇到问题&#xff0c;询问chatGPT后发现问题所在的过程进行记录&#xff0c;当然绝大部分情况下都是batch_size设置太大了&#xff0c;显卡内存不足导致 部分重点代码&#xff1a; 导入模型部分略 #自定义数据集有关类 c…

无人机 PX4 飞控 | EKF2简介与使用方法

无人机 PX4 飞控 | EKF2简介与使用方法 PX4 EKF2简介EKF 的启动ecl EKF 的优缺点缺点优点 运行单个EKF实例运行多个EKF实例 PX4 EKF2简介 PX4是一个流行的开源飞控系统&#xff0c;广泛用于无人机和其他自动驾驶飞行器。EKF2&#xff08;Extended Kalman Filter 2&#xff09;…

IEEE 802.11a OFDM系统的仿真(续)

&#xff08;内容源自详解MATLAB&#xff0f;SIMULINK 通信系统建模与仿真 刘学勇编著第九章内容&#xff0c;有兴趣的读者请阅读原书&#xff09; clear all %%%%%%%参数设计部分%%%%%%%Nsp52;%系统子载波数&#xff08;不包括直流载波&#xff09; Nfft64;%FFT长度 Ncp16;…

ppt文档怎么转换成pdf?快来试试这几种转换方法!

ppt文档怎么转换成pdf&#xff1f;在日常工作与学习的广阔舞台上&#xff0c;PPT&#xff0c;这一演示文稿的常青树&#xff0c;无疑是表达创意、传递信息的重要工具&#xff0c;然而&#xff0c;正如每枚硬币都有其两面&#xff0c;PPT在带来便捷的同时&#xff0c;也显露出一…

js | TypeError: Cannot read properties of null (reading ‘indexOf’) 【解决】

js | TypeError: Cannot read properties of null (reading ‘indexOf’) 【解决】 描述 概述 在前端开发中&#xff0c;遇到TypeError: Cannot read properties of null (reading indexOf)这类错误并不罕见。这个错误通常表明你试图在一个null值上调用indexOf方法&#xff0c…

Linux基础---05输入输出重定向

一.输出重定向符号> 操作1 > 文件 &#xff1a;将操作1的结果覆盖到文件里&#xff0c;并且此文件之前的数据全部清空。 操作2 >>文件&#xff1a;将操作2的结果追加到文件里&#xff0c;原文件的内容不会被清空。 操作3 1>right.txt 2>wrong.txt:操作3的返…

C 盘突然爆满,罪魁祸首竟然是 ...... !

今天打开电脑的时候突然发现 C 盘进度条变红了&#xff0c;这很不正常&#xff01; 做软件开发的应该都会经常在各种磁盘中查找文件和资料&#xff0c;也就会频繁打开 此电脑 窗口&#xff0c;因此即使不是刻意去观察各个磁盘的容量&#xff0c;也会时不时瞟一眼每个盘的占用条…

Java特殊文件xml—利用Dom4J解析xml文件(完整详解,附有代码+案例)

文章目录 三十.特殊文件30.1 xml概述30.1 xml文件30.2 Dom4J解析xml30.2.1 案列130.2.2 案例2 三十.特殊文件 30.1 xml概述 可扩展标记语言 可扩展&#xff1a;标签名字可以自己定义 优点&#xff1a;易于阅读&#xff0c;可以配置成组出现的数据 缺点&#xff1a;解析比较复…

对称矩阵的压缩存储

1.给自己出题&#xff1a;自己动手创造&#xff0c;画一个5行5列的对称矩阵 2.画图&#xff1a;按“行优先”压缩存储上述矩阵&#xff0c;画出一维数组的样子 3.简答&#xff1a;写出元素 i,j 与 数组下标之间的对应关系 4.画图&#xff1a;按“列优先”压缩存储上述矩阵&a…

盐湖卤水中提取铷、铯

盐湖卤水中提取铷、铯是一个复杂但具有重要意义的过程&#xff0c;因为铷、铯是稀有的金属元素&#xff0c;在高科技、航空航天、新能源等领域有广泛应用。以下是从盐湖卤水中提取铷、铯的详细分析&#xff1a;我国盐湖资源丰富&#xff0c;盐类资源总量约12000亿吨&#xff0c…

2024.9.12(k8s环境搭建2)

一、接9.11 19、部署calico的pod 4. 查看容器和节点状态 异常处理&#xff1a; 出现Init:0/3&#xff0c;查看node节点 /var/log/messages是否有除网络异常之外的报错信息 三台机器执行&#xff1a;&#xff08;更新版本&#xff09; yum list kernel yum update kernel reb…

i++与++i在for循环中效果一样?

首先说结果 是的&#xff0c;在Visual Studio 2022中&#xff0c;不同于直接printf&#xff0c;在for循环中的i与i是同样的效果&#xff08;都当作了i&#xff09; 这是编译器干的好事。 如图比对 i i 原因探寻 | i i的底层原理 找到一篇博客&#xff0c;我目前还看不太明…

关于Spring Cloud 表达式注入漏洞——分析复现

更多漏洞分析复现&#xff0c;可前往无问社区查看http://www.wwlib.cn/index.php/artread/artid/5175.html 一、漏洞成因 近期&#xff0c;Spring Cloud官方发布了一则安全公告&#xff0c;修复了一个Spring Cloud Function中的 SPEL表达式注入漏洞。该漏洞是由于Spring Clou…

123.rk3399 uboot(2017.09) 源码分析3(2024-09-12)

啃了几天initf_dm,发现啃不动啊&#xff0c;但是后面的函数比这个简单&#xff0c;要不先把简单的做了吧。 本文接上一篇https://blog.csdn.net/zhaozhi0810/article/details/142050827 一、c的入口 board_init_f 1.3.12 arch_cpu_init_dm&#xff08;common/board_f.c&#…

AWS账号申请指南:必须绑定银行卡吗?

小伙伴们&#xff0c;大家好&#xff01;今天九河云来和大家聊一聊一个常见的问题&#xff1a;申请AWS账号时&#xff0c;是否必须要绑定银行卡呢&#xff1f;相信很多小伙伴在注册AWS账号时都会遇到这个问题。为了帮助大家更好地了解这个过程&#xff0c;小编特意整理了一些信…

SprinBoot+Vue旅游景点管理系统设计与实现

目录 1 项目介绍2 项目截图3 核心代码3.1 Controller3.2 Service3.3 Dao3.4 application.yml3.5 SpringbootApplication3.5 Vue 4 数据库表设计5 文档参考6 计算机毕设选题推荐7 源码获取 1 项目介绍 博主个人介绍&#xff1a;CSDN认证博客专家&#xff0c;CSDN平台Java领域优质…

模 板

导引&#xff1a; 模板是为了解决函数类型不同所重载&#xff0c;带来的麻烦简化。利用一个模板&#xff08;示列&#xff09;代码&#xff0c;让编译器编写出不同类型的代码&#xff0c;满足所需。 int swap(int &p1,int &p2) {int pp1;p1p2;p2p; } char swap(char …