bfs之走迷宫

news2024/10/6 12:29:37

文章目录

    • 走迷宫
    • 广度优先遍历
    • 代码
    • Java代码
    • 打印路径

走迷宫

给定一个 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


广度优先遍历

思路:从起点开始,往前走第一步,记录下所有第一步能走到的点,然后从所第一步能走到的点开始,往前走第二步,记录下所有第二步能走到的点,重复下去,直到走到终点。输出步数即可。

这就是广度优先遍历的思路。

实现方式:广度优先遍历

  1. 用 g 存储地图,f存储起点到其他各个点的距离。

  2. 从起点开始广度优先遍历地图。

  3. 当地图遍历完,就求出了起点到各个点的距离,输出f[n][m]即可。
    在这里插入图片描述

  4. void bfs(int a, int b): 广度优遍历函数。输入的是起点坐标。

  5. queue q;:用来存储每一步走到的点。

  6. while(!q.empty())循环:循环依次取出同一步数能走到的点,再往前走一步。

  7. int dx[4] = {0, 1, 0, -1}, dy[4] = {-1, 0, 1, 0};:一个点往下一步走得时候,可以往上下左右四方向走。

代码

#include <cstring>
#include <iostream>
#include <queue>
using namespace std;
typedef pair<int, int> PII;
const int N = 110;
int g[N][N];//存储地图
int f[N][N];//存储距离
int n, m;
void bfs(int a, int b)//广度优先遍历
{
    queue<PII> q;
    q.push({a, b});
    //初始点的距离为 0.
    //可以不要这一句,因为f初始化的时候,各个点为0
    f[0][0] = 0;
    while(!q.empty())
    {
        PII start = q.front();
        q.pop();
        //这一句可以不要,因为入队的时候就置为了1
        g[start.first][start.second] = 1;
        int dx[4] = {0, 1, 0, -1}, dy[4] = {-1, 0, 1, 0};
        for(int i = 0; i < 4; i++)//往四个方向走
        {
            //当前点能走到的点
            int x = start.first + dx[i], y = start.second + dy[i];
            //如果还没有走过
            if(g[x][y] == 0)
            {
                //走到这个点,并计算距离
                g[x][y] = 1;
                f[x][y] = f[start.first][start.second] + 1;//从当前点走过去,则距离等于当前点的距离+1.
                //这个点放入队列,用来走到和它相邻的点。
                q.push({x, y});
            }

        }
    }
    cout << f[n][m];
}

int main()
{
    memset(g, 1, sizeof(g));
    cin >> n >>m;
    for(int i = 1; i <= n; i++)
    {
        for(int j = 1; j <= m; j++)
        {
            cin >> g[i][j];
        }
    }
    bfs(1,1);

}

Java代码

/***
 * 做这种题目的步骤(最短路问题)
 *1.创建两个存储,一个存储值,一个存储距离
 *2.然后首先将第一个点的位置存储的距离提前标注出来
 *3.然后弄两个方向变量用于上下左右前进int[] dx = {-1,0,1,0}, dy = {0,1,0,-1};
 *4.然后如果四个方向上的点没有超过边界,在结合实际情况有没有用过的点,
 * 判断能不能够进行前进,如果可以就进行前进存储其内容g跟距离d+1
 * 5.最后返回想要的最短值d;
 * **/

import java.io.*;
public class Main{
    static int N = 110,hh,tt,n,m;
    static int[][] g = new int[N][N];//用来存储迷宫地图
    static int[][] d = new int[N][N];//用来存储走的距离
    static PII[] q = new PII[N*N];//用来放每个点的下标
    public static int  bfs(){
        hh = 0 ; tt = -1; //队列的头节点=0,尾节点 = 0;
        d[0][0] = 0; // 我们首先站在的是第一个点,所以值距离设置为0
        q[++tt] = new PII(0,0); //然后将第一个点下标存入q队列中
        //利用向量的方法进行让他上下左右判断是否能够前进
        int[] dx = {-1,0,1,0};//上(-1,0) 下(1,0)
        int[] dy = {0,1,0,-1};//左(0,-1) 右(0,1)
        while(hh <= tt){
            PII t = q[hh++]; //每一次将头结点拿出来
            for(int i = 0 ; i < 4 ; i ++ ){//然后进行下一步要往哪里走,这里可能有多重选择可走
                int x = t.first + dx[i]; //这里进行x轴向量判断
                int y = t.second + dy[i];//这里进行y轴向量的判断
                //如果x,y满足在地图中不会越界,然后地图上的点g是0(表示可以走),
                //然后这里是没走过的距离d是-1;
                if(x >= 0 && x < n && y >= 0 && y < m && g[x][y] == 0 && d[x][y] == -1){
                    //将现在可以走的点(x,y)加上上一个点计数距离的点加上一,就是现在走到的点的距离
                    d[x][y] = d[t.first][t.second] + 1;
                    q[++tt] = new PII(x,y);//然后将这一个可以走的点存入队列尾
                }
            }
        }
        return d[n-1][m-1]; //最后返回的是地图走到尽头最后一个位置的位置统计的距离
    }
    public static void main(String[] args)throws IOException{
        BufferedReader re = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter wt = new BufferedWriter(new OutputStreamWriter(System.out));
        String[] s = re.readLine().split(" ");
        n = Integer.parseInt(s[0]);
        m = Integer.parseInt(s[1]);
        for(int i = 0 ; i < n ;  i ++ ){
            String[] st = re.readLine().split(" ");
            for(int j = 0 ; j < m ;j ++ ){
                g[i][j] = Integer.parseInt(st[j]);
                d[i][j] = -1;
            }
        }
        System.out.println(bfs());
        wt.close();
    }
}
//这是一个用来存储两个坐标的类Pair
class PII{
    int first,second;
    public PII(int first,int second){
        this.first  = first;
        this.second = second;
    }
}

打印路径

#include<bits/stdc++.h>
using namespace std;
const int N = 200;
int n,m;
int d[N][N];//存储从起点到各点的最短距离,初始化为-1,表示未访问过。
int g[N][N];//存储地图信息,0表示可以通过的点,非0表示有障碍物的点。
queue<pair<int,int>> q; //用于BFS搜索的队列,存储点的坐标。
pair<int, int> prevNode[N][N]; //存储每个点的前一个点的坐标,用于追踪路径

int bfs(){
    memset(d,-1,sizeof d);// 初始化所有点的最短距离为-1
    d[1][1] = 0; //首先将起点(1, 1)的最短距离设置为0,表示从起点到起点的距离为0,
    q.push({1,1}); //把起点放入队列中。

    int dx[4] ={0,0,-1,1},dy[4] = {1,-1,0,0};//上下左右

    while(q.size()){//当队列中还有坐标
        auto t = q.front();  // 获取队列前端元素,即当前处理的点
        q.pop(); // 弹出当前处理的点
        for(int i = 0;i < 4;i++){
            int x = t.first + dx[i],y = t.second + dy[i];//遍历四个方向
            //如果这个相邻点有效(在网格范围内)、未被访问过(d[x][y] == -1)、且没有障碍物(g[x][y] == 0),
            if(x >= 1 && y >= 1 && x <= n && y <= m && d[x][y] == - 1 && g[x][y] == 0){//记住是y <= m不是y <= n
                d[x][y] = d[t.first][t.second] + 1; //更新这个点的最短距离为d[t.first][t.second] + 1
                prevNode[x][y] = t; // 记录前驱点,是由t来到(x,y)的。
                q.push({x,y}); //将其坐标加入队列中。
            }
        }
    }
    //循环结束后,d[n][m]中存储的就是从起点(1, 1)到终点(n, m)的最短距离。
    //如果终点不可达,结果将保持为初始化时的-1。
    return d[n][m];
}

void print_path() {
    if (d[n][m] == -1) {
        cout << "终点不可达。" << endl;
        return;
    }
    vector<pair<int, int>> path;
    // 从终点开始逆向追踪到起点

    //这里为什么逆向追踪呢?因为我们储存的是前驱节点,我们只知道到达了终点(n,m),所以要先找(n,m)的前驱节点a,
        //再找a的前驱节点b,直到到达(1,1)
    //这个过程就像是沿着一条线索,从故事的结局逐步回溯到开头一样。
    //make_pair(1, 1) 创建了一个包含两个整数的 pair
    for (pair<int, int> at = {n, m}; at != make_pair(1, 1); at = prevNode[at.first][at.second]) {
        path.push_back(at);
    }

    path.push_back({1, 1}); // 加入起点
    reverse(path.begin(), path.end()); // 将路径逆序,因为我们是逆向追踪的

    for (auto p : path) {
        cout << "(" << p.first << ", " << p.second << ")" << " -> ";
    }
    cout << "End" << endl;
}

int main() {
    cin >> n >> m;
    for(int i = 1;i <= n;i++){
        for(int j = 1;j <= m;j++){
            cin >> g[i][j];
        }
    }

    cout << bfs() << endl; // 执行BFS搜索并输出从起点到终点的最短距离
    print_path(); // 打印找到的路径

    return 0;
}

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

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

相关文章

MATLAB绘制蒸汽压力和温度曲线

蒸汽压力与温度之间的具体关系公式一般采用安托因方程&#xff08;Antoine Equation&#xff09;&#xff0c;用于描述纯物质的蒸汽压与温度之间的关系。安托因方程的一般形式如下&#xff1a; [\log_{10} P A - \frac{B}{C T}] 其中&#xff0c; (P) 是蒸汽压&#xff08…

syncGradle项目时报错Unknown Kotlin JVM target: 22

解决方案1 定位到build.gradle.kts的出问题行&#xff0c;将其注释掉然后把sourceCompatibility行也注释掉重新sync. 这样会自动使用默认兼容的版本 你也可以根据文档手动解决兼容问题2 Configure a Gradle project | Kotlin Documentation (kotlinlang.org) ↩︎ Compatibil…

[VulnHub靶机渗透] Hackademic: RTB1

&#x1f36c; 博主介绍&#x1f468;‍&#x1f393; 博主介绍&#xff1a;大家好&#xff0c;我是 hacker-routing &#xff0c;很高兴认识大家~ ✨主攻领域&#xff1a;【渗透领域】【应急响应】 【Java、PHP】 【VulnHub靶场复现】【面试分析】 &#x1f389;点赞➕评论➕收…

一、Vagrant搭建相关环境

目录 一、创建Vagrant相关环境1.下载安装VirtualBox2.在BlOS中设置CPU虚拟化3.使用Vagrant新建linux虚拟机3.1下载Vagrant3.2Vagrant官方镜像仓库3.3使用Vagrant初始化一个centos7的虚拟机 4.设置固定ip地址 二、安装docker1.按照docker 三、docker安装一些中间件1.mysql安装2.…

Elasticsearch:理解人工智能相似性搜索

理解相似性搜索&#xff08;也称为语义搜索&#xff09;的指南&#xff0c;这是人工智能最新阶段的关键发现之一。 最新阶段人工智能的关键发现之一是根据相似性搜索和查找文档的能力。相似性搜索是一种比较信息的方法&#xff0c;其基于含义而非关键字。 相似性搜索也被称为语…

【隧道篇 / WAN优化】(7.4) ❀ 01. 启动WAN优化 ❀ FortiGate 防火墙

【简介】几乎所有的人都知道&#xff0c;防火墙自带的硬盘是用来保存日志&#xff0c;以方便在出现问题时能找到原因。但是很少的人知道&#xff0c;防火墙自带的硬盘其实还有另一个功能&#xff0c;那就是用于WAN优化。 防火墙自带的硬盘 在FortiGate防火墙A、B、C、D系列&…

MWeb Pro for Mac:功能强大的Markdown博客编辑器

MWeb Pro for Mac是一款功能强大的Markdown博客编辑器&#xff0c;专为Mac用户设计&#xff0c;提供了一站式的博客写作和发布体验。这款软件不仅支持Markdown语法&#xff0c;还提供了丰富的编辑和排版功能&#xff0c;让用户能够轻松创建出精美的博客内容。 MWeb Pro的即时预…

每日一题4:Pandas创建新列

一、每日一题 一家公司计划为员工提供奖金。 编写一个解决方案&#xff0c;创建一个名为 bonus 的新列&#xff0c;其中包含 salary 值的 两倍。 返回结果格式如下示例所示。 解答&#xff1a; import pandas as pddef createBonusColumn(employees: pd.DataFrame) -> pd.D…

Redis高级(Redis持久化,Redis主从模式,Redis哨兵模式,Redis分片集群)

目录 一、单机Redis 1. 问题说明 2. 安装Redis 1 解压安装Redis【备用】 2 配置Redis 3 启动Redis 3. 小结 二、Redis持久化 1. 持久化机制介绍 2. RDB模式 3. AOF模式 4. RDB和AOF对比 5. 小结 三、Redis主从模式 1. 介绍 2. 搭建Redis主从架构【备用】 3. 主…

微服务领域的寻路者 —— Eureka深度探索与实战秘籍

文章目录 一、引言定义目标一个接地气的例子引言小结 二、Eureka架构2.1 Eureka Server一个有趣的例子2.2 Eureka Client一段简单的代码示例架构小结 三、工作流程1. 服务注册2. 心跳检测3. 服务发现4. 健康检查与失效剔除工作流程小结 四、核心机制4.1 服务注册与续约4.2 服务…

2024年03月 Scratch 图形化(三级)真题解析#中国电子学会#全国青少年软件编程等级考试

Scratch图形化等级考试(1~4级)全部真题・点这里 一、单选题(共18题,共50分) 第1题 运行程序后,角色一定不会说出的数字是?( ) A:2 B:4 C:6 D:8 答案:A 程序中随机数的取值最小为 2,最大为 20 ,那么随机数加上 2 之后的结果的最小值为 4 ,最大值为 22 。所…

设备树与/sys/bus/platform/devices与/sys/devices目录关系

设备树与sys/bus/platform/devices sysfs文件系统中/sys/bus/platform/devices下的设备是由设备树生成&#xff0c; 根节点下有compatible的子节点都会在/bus/platform/devices生成节点 总线 I2C、SPI 等控制器会在/bus/platform/devices生成节点 总线 I2C、SPI 节点下的子节点…

为什么电子商务安全是速度和保护之间的平衡行为

微信搜索关注公众号网络研究观&#xff0c;获取更多信息。 电子商务世界是一把双刃剑。虽然它为企业和消费者提供了便利和可访问性&#xff0c;但它也为网络犯罪分子提供了诱人的目标。在这个不断变化的环境中&#xff0c;优先考虑安全不再是一种选择&#xff1b;而是一种选择&…

Reactor Netty TCP 服务器端-响应式编程-011

🤗 ApiHug {Postman|Swagger|Api...} = 快↑ 准√ 省↓ GitHub - apihug/apihug.com: All abou the Apihug apihug.com: 有爱,有温度,有质量,有信任ApiHug - API design Copilot - IntelliJ IDEs Plugin | Marketplace The Next Generation API Development Platform…

【LeetCode】环形队列实现

目录 前言1. 环形队列概念2. 循环队列实现设计3. 功能实现3.1 定义3.2 初始化3.3 判断队列是否为空3.4 判断队列是否为满3.5 入栈3.6 出栈3.7 获取队头数据3.8 获取队尾数据3.9 销毁 4. 总结5. 完整通过代码 前言 之前我们学习环形链表相关问题&#xff0c;现在我们来看看环形…

opencv_21_直方图均衡化

1&#xff09;void histogram_eq_demo(Mat& image); 2&#xff09;void ColorInvert::histogram_eq_demo(Mat& image) { Mat gray; cvtColor(image, gray, COLOR_BGR2GRAY); imshow("灰度图像", gray); Mat dst; equalizeHist(gray, ds…

B2985A是德科技B2985A高阻计

181/2461/8938产品概述&#xff1a; B2985A 静电计/高阻表 描述 B2985A 静电计/高阻表是全球少有具有图形显示功能的静电计&#xff0c;可凭借 0.01 fA&#xff08;0.01 x 10-15 A&#xff09;的分辨率帮助您可靠测量弱电流&#xff0c;并可测量高达 10 PΩ&#xff08;10 x 1…

基于FPGA的去雾算法

去雾算法的原理是基于图像去模糊的原理&#xff0c;通过对图像中的散射光进行估计和去除来消除图像中的雾霾效果。 去雾算法通常分为以下几个步骤&#xff1a; 1. 导引滤波&#xff1a;首先使用导引滤波器对图像进行滤波&#xff0c;目的是估计图像中散射光的强度。导引滤波器…

C++ | Leetcode C++题解之第73题矩阵置零

题目&#xff1a; 题解&#xff1a; class Solution { public:void setZeroes(vector<vector<int>>& matrix) {int m matrix.size();int n matrix[0].size();int flag_col0 false;for (int i 0; i < m; i) {if (!matrix[i][0]) {flag_col0 true;}for …

C语言 | Leetcode C语言题解之第73题矩阵置零

题目&#xff1a; 题解&#xff1a; void setZeroes(int** matrix, int matrixSize, int* matrixColSize) {int m matrixSize;int n matrixColSize[0];int flag_col0 false;for (int i 0; i < m; i) {if (!matrix[i][0]) {flag_col0 true;}for (int j 1; j < n; j…