广度优先搜索--什么是“BFS”?为什么要用队列实现?--走迷宫代码详细注释

news2024/11/25 10:24:09

目录

  • 什么是“DFS”
  • 什么是“BFS”
  • 为什么要用队列?
  • 举例(走迷宫):

什么是“DFS”

DFS 全称是 Depth First Search,中文名是深度优先搜索,是一种用于遍历或搜索树或图的算法。
在这里插入图片描述
深度优先,就是每次都尝试向更深的节点走。

什么是“BFS”

BFS全称是 Breadth First Search,中文名是宽度优先搜索,也叫广度优先搜索
其中的广度优先,就是每次都尝试访问同一层的节点, 如果同一层都访问完了,再访问下一层。
在这里插入图片描述
这样做的结果是,BFS 算法找到的路径是从起点开始的最短合法路径。换言之,这条路径所包含的边数最小。也就是说通过BFS算法只要找到目标节点,该路径就是最短路径。

为什么要用队列?

队列的原理是先进先出,而广度优先搜索类似于树的层次遍历,从离根节点最近的点开始向外扩散,因此用队列将最先遍历的点存入,后遍历的点后存入,符合bfs的逻辑。

首先我们先看BFS的节点处理顺序:
第一轮:处理根节点(第一层节点)
第二轮:处理根节点的所有子节点(第二层节点)
第三轮:处理距离根节点两步的所有节点(第三层节点)

然后我们对比队列的入队和出队顺序:
首先将根节点入队
第一轮:将根节点出队,对根节点进行处理,然后将所有的邻居(根节点的所有子节点)入队。但是新添加的节点不会立即遍历,而是在下一轮中处理。
结点的处理顺序与它们添加到队列的顺序是完全相同的顺序,即先进先出(FIFO)。这就是我们在 BFS 中使用队列的原因。

举例(走迷宫):

在这里插入图片描述

主要思想就是需要定义一个队列,和一个标记数组,标记数组主要用来记录步数,并且判断是否走过(该节点是否已经处理过)。
首先将入口坐标入队,并且将入口坐标在标记数组的值改为0(表示当前0步)
其次进入循环,将入口坐标进行出队,然后上下左右遍历,当相邻节点符合条件时将该节点入队,并且更新该节点在标记数组的值+1(表明当前距离起点有1步)。再进行判断该节点是否等于出口。如果等于直接返回当前步数。
然后再进行循环,对相邻节点。因为队列的特性,优先处理的都是相邻节点。
因此当找到出口位置时,就是最优路径。

#include <iostream>
#include <bits/stdc++.h>
using namespace std;

typedef pair<int, int> PII;
// 定义地图
int ditu[110][110];
// 标记节点,没走过的初始化为-1,走过的标记为1
int label[110][110];
// 定义地图大小,N行M列 
int N, M;
// 定义坐标入口x_r,y_r,出口x_c,y_c
int x_r, y_r, x_c, y_c;
// 定义队列
queue<PII> q;

// 广度优先搜索
int bfs()
{
  // 初始化标记数组
  memset(label, -1, sizeof(label));
  label[x_r][y_r] = 0;
  // 将即将搜索的节点压入队列
  q.push({x_r, y_r});
  // 定义上下左右
  int x_move[4] = {-1, 0, 1, 0}, y_move[4] = {0, 1, 0, -1};
  // 当队列不为空时则路径没有全部遍历结束,为空说明地图全部走完
  while(q.size())
  {
    // 将节点取出
    auto head = q.front();
    q.pop();
    // 将该节点进行移动
    for(int i=0; i<4; i++)
    {
      // 更新移动后的位置
      int x = head.first + x_move[i];
      int y = head.second + y_move[i];
      // 对更新后的位置进行判断
      // 满足在边界内,该位置没有障碍物,该位置没有走过(没有被标记过)
      if(x>=1 && x <= N && y>=1 && y<=M && ditu[x][y]==1 && label[x][y]==-1)
      {
        // 记录步数,当前节点与入口的距离
        label[x][y] = label[head.first][head.second] + 1;
        // 给当前节点入队,在下次循环时以该节点为起始进行上下左右
        q.push({x,y});
        // 判断当前位置是否是出口,如果是则返回步数
        if(x==x_c && y==y_c)
        {
          return label[x][y];
        }
      }
    }
  }
  // 如果所有节点都遍历结束都没有出口,则返回-1
  return -1;
}
int main()
{
  // 输入地图大小
  cin >> N >> M;
  for(int i=1; i<=N; i++)
  {
    for(int j=1; j<=M; j++)
    {
      cin >> ditu[i][j];
    }
  }
  cin >> x_r >> y_r >> x_c >> y_c;
  cout << bfs();
  return 0;
}

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

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

相关文章

uni-admin初始化一直提示未初始化数据库问题

uni-admin初始化&#xff0c;一直提示&#xff1a; “检测到您未初始化数据库&#xff0c;请先右键uni-admin项目根目下的 uniCloud/database 目录&#xff0c;执行初始化云数据库&#xff0c;否则左侧无法显示菜单等数据” 最后清除了localStorage&#xff0c;发现就好了。

【MySQL】数据操作语句(DML)

&#x1f466;个人主页&#xff1a;Weraphael ✍&#x1f3fb;作者简介&#xff1a;目前学习计网、mysql和算法 ✈️专栏&#xff1a;MySQL学习 &#x1f40b; 希望大家多多支持&#xff0c;咱一起进步&#xff01;&#x1f601; 如果文章对你有帮助的话 欢迎 评论&#x1f4ac…

2.Spring 核心与设计思想

文章目录 1.Spring 是什么&#xff1f;1.1 什么是容器&#xff1f;1.2 什么是 IoC&#xff1f;1.2.1 传统程序开发1.2.2 控制反转式程序开发1.2.3 对比总结规律 1.3 理解 Spring IoC1.4 DI 概念说明 2.总结2.总结 大家好&#xff0c;我是晓星航。今天为大家带来的是 Spring核心…

vue3从精通到入门18:依赖注入Provide / Inject

provide 和 inject 是一对用于实现依赖注入的 API。provide 选项允许父组件向其所有子组件提供一个依赖&#xff0c;无论组件层次结构有多深&#xff0c;只要在其后代组件中使用 inject 选项&#xff0c;就可以访问到这个依赖。 父组件 (ParentComponent.vue) <template>…

抖音评论ID提取工具|视频关键词评论批量采集软件

抖音评论ID提取工具&#xff1a;批量抓取抖音评论 抖音评论ID提取工具是一款功能强大的软件&#xff0c;可以帮助您批量抓取抖音视频下的评论信息。通过输入关键词和评论监控词&#xff0c;即可进行评论的抓取&#xff0c;并提供评论昵称、评论日期、评论内容、命中关键词以及所…

C++笔记(函数重载)

目录 引入&#xff1a; 定义&#xff1a; 易错案例&#xff1a; 引入&#xff1a; 对于实现相似功能的函数&#xff0c;在命名时&#xff0c;我们常会出现命名重复的问题。对于C语言&#xff0c;编译器遇到这种命名重复的情况&#xff0c;会进行报错。而我们的C为了更方便程…

[23年蓝桥杯H题] 合并石子

问题描述 在桌面从左至右横向摆放着 N 堆石子。每一堆石子都有着相同的颜色&#xff0c;颜 色可能是颜色 0 &#xff0c;颜色 1 或者颜色 2 中的其中一种。 现在要对石子进行合并&#xff0c;规定每次只能选择位置相邻并且颜色相同的两堆 石子进行合并。合并后新堆的相对位置保…

Python对docx文本一些操作

文本要是docx结尾 安装 Python-docx 包 读取word from docx import Document doc Document("c:/word22.docx") 获取word中的所有表格 from docx import Document doc Document("c:/word22.docx") doc.tables # 返回所有表格的list 获取表格中的总行…

2022年蓝桥杯省赛——直线

目录 题目链接&#xff1a;11.直线 - 蓝桥云课 (lanqiao.cn) 题目描述 思路 代码思路如下 代码实现 坑来喽~~ 导致这个BUG的原因&#xff01;&#xff01;&#xff01; 总结 整体的 两种b的情况对比数据 题目链接&#xff1a;11.直线 - 蓝桥云课 (lanqiao.cn) 题目描…

Linux LVM磁盘扩容

1、查看磁盘情况 df -h df -h2、查看逻辑卷 lvdisplay lvdisplay3、查看逻辑组 vgdisplay vgdisplay4、查看物理卷 pvdisplay pvdisplay5、查看磁盘 fdisk -l fdisk -l6、磁盘分区fdisk /dev/磁盘名 # 上一步查看到的新硬盘路径 fdisk /dev/vdb7、格式化磁盘mkfs -t ext4…

移除chromeDriver脚本文件

#!/bin/bash process_namechromedriver process_name2webdriver #查找并杀死进程名 PIDps -ef |grep $process_name|grep -v grep|awk {print $2}|xargs PID2ps -ef |grep $process_name2|grep -v grep|awk {print $2}|xargs save_file"/usr/local/software/ship/sadmin/…

好用的Android Studio插件管理器

1.使用阿里云的通义灵码方便快速开发 1.1下载插件File->plugin->marketplace 搜索 Tongyilingma然后安装重启登录阿里云&#xff0c;确认 1.2 使用方法 输入信息描述 比如 //写一段冒泡排序然后换行&#xff0c;输入public/private/protected方法会自动生成联想代码…

javaWeb网上零食销售系统

1 绪 论 目前&#xff0c;我国的网民数量已经达到7.31亿人&#xff0c;随着互联网购物和互联网支付的普及&#xff0c;使得人类的经济活动进入了一个崭新的时代。淘宝&#xff0c;京东等网络消费平台功能的日益完善&#xff0c;使得人们足不出户就可以得到自己想要的东西。如今…

短剧查询前端程序带 API 后台管理

搭建教程 1 上传到服务器后&#xff0c;访问下 ip/api.php 2 这样就会自动创建表 3 然后在 config.php 填写数据库相关信息&#xff0c;在 admin.php 填写账号密码信息 4 访问 ip/admin.php 进去后台 5 批量插入数据格式为 短剧名短裤链接 举例&#xff1a;你好https://q…

【建议收藏合集整理】国一大佬带你,蓝桥杯Java组拿奖基础知识整理集合,看完,3天冲蓝桥杯省一。

前文引导 此文章为系统训练&#xff0c;建议反复观看&#xff0c;将所有例题的知识点掌握&#xff0c;文章结尾将分享新手如何通过3天达到冲击蓝桥杯省一的实力。 蓝桥杯Java知识点记忆&#xff08;必须熟练记忆&#xff09; 以下内容必须掌握 &#xff08;1&#xff09;输入…

CRM集成:解锁业务增长与客户关系管理的关键

预计从2021年至2028年&#xff0c;CRM领域的市场规模将大幅跃升&#xff0c;从约580亿美元增长至1290亿美元。这一显著的增长并非偶然&#xff0c;而是源于CRM平台为企业带来的巨大价值。客户关系管理平台助力销售高效开发潜在客户&#xff0c;客户成功经理有效支持客户&#x…

多维 HighCharts

1&#xff1a;showHighChart.html <!DOCTYPE html> <html lang"zh-CN"><head><meta charset"UTF-8"><!-- js脚本都是官方的,后两个是highchart脚本 --><script type"text/javascript" src"jquery1.7.1.mi…

蓝桥杯-求阶乘

问题描述 满足 N!的末尾恰好有 区 个o的最小的 N 是多少? 如果这样的 N 不存在输出 -1。 输入格式 一个整数 区。 输出格式 一个整数代表答案。 样例输入 样例输出 10 评测用例规模与约定 对于 30% 的数据,1<K<106 对于 100% 的数据,1<K<1018 运行限制 最大运行时…

lua学习笔记14(协程的学习)

print("*****************************协程的学习*******************************") --创建1 coroutine.create(function()) 使用1 coroutine.resume(co) -- 创建2 co2coroutine.wrap(fun) 使用2 co2() --协程的挂起函数 coroutine.yield() --协程的状态 --c…