bfs之走迷宫

文章目录

    • 走迷宫
    • 广度优先遍历
    • 代码
    • 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.mfbz.cn/a/597138.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

leetcode-岛屿数量-99

题目要求 思路 1.使用广度优先遍历&#xff0c;将数组中所有为1的元素遍历一遍&#xff0c;遍历过程中使用递归&#xff0c;讲该元素的上下左右四个方向的元素值也置为0 2.统计一共执行过多少次&#xff0c;次数就是岛屿数量 代码实现 class Solution { public:int solve(vec…

mac电脑如何安装python及环境搭建

&#xff08;1&#xff09;进入官网&#xff1a;Download Python | Python.org&#xff0c;根据自己电脑选择python (2)这里我选择的是mac,点击&#xff1a;macos&#xff0c;选择最近版本并点击进入 (3)选择mac版本&#xff1a; (4)点击就可以进入下载&#xff1a; (5)下载好之…

网站防御XSS攻击的有效策略与实施步骤

随着互联网应用的普及与发展&#xff0c;网站安全已成为众多企业关注的焦点&#xff0c;而XSS&#xff08;Cross-Site Scripting&#xff09;攻击作为最常见的Web安全漏洞之一&#xff0c;对用户数据安全构成严重威胁。本文将详细介绍网站如何有效防御XSS攻击&#xff0c;并提供…

Spring JdbcTemplate使用临时表+事务会话管理实现数据新增、查询及自动清除功能

需求描述&#xff1a; 由于某些情况下当查询过滤参数过大时&#xff0c;执行sql由于参数过大而报错&#xff0c;此时 需要使用临时表的方式&#xff0c;即 当参数超过某个阀值&#xff08;如 1000&#xff0c;可调整&#xff09;新增一张临时表&#xff0c;将原表 与 该临时表进…

2024精武杯部分复现

首先是计算机部分&#xff0c;这里是题目 做完才发现其实很多东西在火眼里面已经有更快的捷径了&#xff0c;但是自己当时没发现&#xff0c;还去傻傻的开虚拟机去找&#xff0c;说到底&#xff0c;还是对取证软件的理解不够&#xff0c;也不怎么会用。不废话了&#xff0c;直接…

怎么给word文件名批量替换部分文字?word设置批量替换文字教程

批量替换Word文件名中的几个字&#xff0c;对于经常处理大量文件的人来说&#xff0c;是一项非常实用的技能。以下是一个详细的步骤指南&#xff0c;帮助你快速完成这项任务。 首先&#xff0c;你需要准备一个可以批量重命名文件的工具。市面上有很多这样的工具可供选择&#x…

人工智能的发展将如何重塑网络安全

微信搜索关注公众号网络研究观&#xff0c;获取更多信息。 人们很容易认为人工智能 (AI) 真正出现是在 2019 年&#xff0c;当时 OpenAI 推出了 ChatGPT 的前身 GPT-2。 但现实却有些不同。人工智能的基础可以追溯到 1950 年&#xff0c;当时数学家艾伦图灵发表了题为“计算机…

密码学《图解密码技术》 记录学习 第十四章

目录 十四章 14.1 本章学习的内容 14.2 什么是 SSL/TLS 14.2.1 Alice 在 Bob 书店买书 14.2.2 客户端与服务器 14.2.3 АSSL/TLS 承载HTTP 14.2.4 SSL/TLS的工作 14.2.5 SSL/TLS也可以保护其他的协议 14.2.6 密码套件 14.2.7 SSL 与 TLS 的区别 14.3 使用 SSL/TLS 进…

产业观察:电机驱动成为人形机器人的动力核心

前不久&#xff0c;波士顿动力发布一则“再见&#xff0c;液压Atlas”视频&#xff0c;宣告其著名的液压驱动双足人形机器人Atlas正式退役。这则视频引起全球所有Atlas粉丝的高度关注。然而紧接着&#xff0c;波士顿动力便又推出了全部由电机驱动的新一代Atlas机器人&#xff0…

【Git】【MacOS】Github从创建与生成SSH公钥

创建账号 这一步不过多赘述&#xff0c;根据自己的邮箱新创建一个账号 配置SSH公钥 本人是macOS系统&#xff0c;首先从终端输入 cd ~/.ssh进入.ssh目录,然后通过 ls查看有没有一个叫做id_rsa.pub的文件 本人之前生成过SSH公钥,如果没有的话&#xff0c;通过 ssh-keygen -t…

luci框架相关笔记

luci架构 LuCI 架构采用了MVC&#xff08;Model-View-Controller&#xff09;设计模式&#xff0c;各个目录的作用如下&#xff1a; model&#xff08;模型&#xff09;: 位于 /usr/lib/lua/luci/model 下&#xff0c;存放了与系统配置相关的模型脚本。这些脚本负责与底层系统…

cmd输入mysql -u root -p无法启动

问题分析&#xff1a;cmd输入mysql -u root -p无法启动 解决方法&#xff1a;配置系统环境变量 1.找到mysql安装文件下的bin文件&#xff1a;&#xff08;复制改文件地址,如下图所示&#xff09; 2.电脑桌面下方直接搜索环境变量并进入&#xff0c;如下图 3.点击环境变量&a…

读取打包到JAR中的文件:常见问题与解决方案(文件在但是报错not find)

读取打包到JAR中的文件&#xff1a;常见问题与解决方案 喝淡酒的时候&#xff0c;宜读李清照&#xff1b;喝甜酒时&#xff0c;宜读柳永&#xff1b;喝烈酒则大歌东坡词。其他如辛弃疾&#xff0c;应饮高梁小口&#xff1b;读放翁&#xff0c;应大口喝大曲&#xff1b;读李后主…

Python数据清洗与可视化实践:国际旅游收入数据分析

文章目录 概要整体流程名词解释NumPyPandasMatplotlibre 技术细节数据清洗可视化 小结 概要 在本篇博客中&#xff0c;我们将通过一个实际的案例&#xff0c;演示如何使用Python进行数据清洗和可视化&#xff0c;以分析国际旅游收入数据。我们将使用Python中的Pandas库来进行数…

04-25 周四 FastBuild重构实践-TLS、全局捕获异常、一键配置

04-25 周四 FastBuild重构实践 时间版本修改人描述04-25V0.1宋全恒新建文档2024年5月6日14:33:16V1.0宋全恒完成文档撰写 简介 由于 04-22 周日 阿里云-瑶光上部署FastBuild过程(配置TLS、自定义辅助命令)描述了重新部署一个FastBuild实例的过程&#xff0c;通过阅读这个&…

线性表的概念与结构,以及顺序表和链表的简单概念

1.线性表 线性表&#xff08;linear list&#xff09;是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构&#xff0c;常见的线性表&#xff1a;顺序表、链表、栈、队列、字符串... 线性表在逻辑上是线性结构&#xff0c;也就说是连续的一条直线…

JS hook cookie

JS hook cookie cookie 的值是V&#xff0c;v是动态变化的 可以看到D中生成了cookie的值n 尝试使用RPC定位到cookie。 替换内容&#xff0c;下断点。 将写好的RPC代码直接插入 加入代码&#xff0c;file.virjar.com/sekiro_web_client.js?_123 这个地址是在前端创建客户端…

开源模型应用落地-CodeQwen模型小试-小试牛刀(一)

一、前言 代码专家模型是基于人工智能的先进技术&#xff0c;它能够自动分析和理解大量的代码库&#xff0c;并从中学习常见的编码模式和最佳实践。这种模型可以提供准确而高效的代码建议&#xff0c;帮助开发人员在编写代码时避免常见的错误和陷阱。 通过学习代码专家模型&…

【网络知识】光猫、路由器 和 交换机 的作用和区别?

数字信号&#xff1a;是指自变量是离散的、因变量也是离散的信号&#xff0c;这种信号的自变量用整数表示&#xff0c;因变量用有限数字中的一个数字来表示。在计算机中&#xff0c;数字信号的大小常用有限位的二进制数表示。 模拟信号&#xff1a;模拟信号是指用连续变化的物…

学习c#第26天 面向对象基础之类与对象

1.类 1.什么是类? 俗话说&#xff0c;“物以类聚&#xff0c;人以群分”。意思是同类的东西经常聚在一起&#xff0c;志同道合 的人相聚成群。前者说物&#xff0c;后者说人。这里以物来进行举例说明[见图]&#xff1a; 水果超市&#xff0c;所有同类的水果摆放在一起&#xf…
最新文章