搜索与图论-BFS

news2024/11/24 3:29:48

文章目录

  • 一、BFS
    • 1. BFS 简介
    • 2. BFS 的基本思想
    • 3. BFS 的实现步骤
    • 4. BFS 的实际演示
  • 二、BFS 例题——走迷宫
    • 具体实现
      • 1. 样例演示
      • 2. 实现思路
      • 3. 代码注解
      • 4. 实现代码
  • 三、BFS 例题——八数码
    • 具体实现
      • 1. 实现思路
      • 2. 代码注解
      • 3. 实现代码

一、BFS

  • BFS 的关键点是状态的选取和标记。

1. BFS 简介

  • BFS,其英文全称是 Breadth First Search,即广度优先算法。是最简便的图的搜索算法之一,这一算法也是很多重要的图的算法的原型。
  • BFS 属于一种盲目搜寻法,目的是系统地展开并检查图中的所有节点,以找寻结果。换句话说,它并不考虑结果的可能位置,彻底地搜索整张图,直到找到结果为止。
  • BFS 搜索时是一层一层的搜索的。可以用来解决最短路问题,是一个从近到远的扩散过程。
  • BFS 主要应用于非加权图(或者所有边的权重相同,如若不相同的话则需采用其他的算法)中任两点的最短路径,寻找其中一个连通分支中的所有点。

2. BFS 的基本思想

  • 从初始状态 S 开始,利用规则,生成所有可能的状态。
  • 构成树的下一层节点,检查是否出现目标状态 G ,若未出现,就对该层所有状态节点,分别顺序利用规则,再生成下一层的所有状态节点,对这一层的所有状态节点检查是否出现 G 。
  • 若未出现,继续按上面思想生成再下一层的所有状态节点,这样一层一层往下展开。
  • 直到出现目标状态为止。

3. BFS 的实现步骤

  • (1) 初始化队列和所求的值。
  • (2) 判断是否为空并取出队头。
  • (3) 利用队头去扩展。
  • (4) 如果符合,将该点入队。
  • 基本框架如下:
void bfs(){
	queue<int>q;
	q.push(初始位置);
	//初始化
	
	while(q.size()){
        int t = q.front();
        q.pop();//取出队头的点,用该点向周围扩散。
		if(check(j)){       //如果该点可行就将它加入队列中
        q.psuh(j);		
        //实施相应的操作 
        }
	} 
}

4. BFS 的实际演示

  • BFS 在面临一个路口时,会把所有的岔路口都记下来,然后选择一个进入其中,把它的分离情况记录下来,然后再返回来进入另外一个岔路,并重复进行这样的操作。如下图所示:
  • (1) 从黑色起点出发,记录所有的岔路口,并标记为走一步可以到达的。

在这里插入图片描述

  • (2) 在此,我们选择黑色起点上方的路径,然后将这个路口可走的方向记录下来并标记为 2 ,意味着走两步可以到达的地方。

在这里插入图片描述

  • (3) 随后,我们回到黑色起点右手边路径为 1 的方块上,并将其能走得方向也记录下来,同样标记为 2 ,因为也是走两步就可以到达的地方。

在这里插入图片描述

  • (4) 此时,距离黑色起点路径为 1 和路径为 2 的方块就已经全都找到了。下面同理,我们可以迅速将路径为 3 的方块找到。

在这里插入图片描述
-(5) 后续,距离黑色起点路径为 4 和路径为 5 的方块也是同理。

在这里插入图片描述
-(6) 通过如上步骤,我们便成功寻找到了路径,并且把所有可行的路径都求出来,

二、BFS 例题——走迷宫

题目描述

给定一个 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. 样例演示

  • 具体演示如下图所示。
    在这里插入图片描述

2. 实现思路

  • 详细如样例演示所示。

3. 代码注解

  • g[N][N];存储地图,d[N][N];存储起点到其他各个点的距离。
  • queue q;用来存储每一步走到的点。
  • while(!q.empty());循环依次取出同一步数能走到的点,再往前走一步。
  • int dx[4] = {0, 1, 0, -1},;dy[4] = {-1, 0, 1, 0};一个点往下一步走得时候,可以往上下左右四方向走。

4. 实现代码

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

typedef pair<int, int> PII;

const int N = 110;

int n, m;
int g[N][N], d[N][N];

int bfs()
{
    queue<PII> q;

    memset(d, -1, sizeof d);
    d[0][0] = 0;
    q.push({0, 0});

    int dx[4] = {-1, 0, 1, 0};
    int dy[4] = {0, 1, 0, -1};

    while (q.size())
    {
        auto t = q.front();
        q.pop();

        for (int i = 0; i < 4; i ++ )
        {
            int x = t.first + dx[i];
            int y = t.second + dy[i];

            if (x >= 0 && x < n && y >= 0 && y < m && g[x][y] == 0 && d[x][y] == -1)
            {
                d[x][y] = d[t.first][t.second] + 1;
                q.push({x, y});
            }
        }
    }

    return d[n - 1][m - 1];
}

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

    cout << bfs() << endl;
    system("pause");
    return 0;
}

三、BFS 例题——八数码

题目描述

在一个 3×3 的网格中,1∼8 这 8 个数字和一个 x 恰好不重不漏地分布在这 3×3 的网格中。
例如:

1 2 3
x 4 6
7 5 8

在游戏过程中,可以把 x 与其上、下、左、右四个方向之一的数字交换(如果存在)。
我们的目的是通过交换,使得网格变为如下排列(称为正确排列):

1 2 3
4 5 6
7 8 x

例如,示例中图形就可以通过让 x 先后与右、下、右三个方向的数字交换成功得到正确排列。
交换过程如下:

1 2 3
x 4 6
7 5 8

1 2 3
4 x 6
7 5 8

1 2 3
4 5 6
7 x 8

1 2 3
4 5 6
7 8 x

现在,给你一个初始网格,请你求出得到正确排列至少需要进行多少次交换。

输入格式

输入占一行,将 3×3 的初始网格描绘出来。
例如,如果初始网格如下所示:

1 2 3
x 4 6
7 5 8

则输入为:1 2 3 x 4 6 7 5 8

输出格式

输出占一行,包含一个整数,表示最少交换次数。
如果不存在解决方案,则输出 −1。

输入样例

2 3 4 1 5 x 7 6 8

输出样例

19

具体实现

1. 实现思路

  • 暴力穷举。穷举出所有给定序列通过交换能得到的新序列,在穷举过程中保存交换次数。
  • 在穷举过程中,如果出现了结果序列,就输出交换次数。否则不能得到结果序列,输出 -1。

在这里插入图片描述

  • 在此中间,我们可以使用字符串来表示表格中的状态,将 3x3 的数组表示成一行。
  • 用一个队列保存当前获得的序列。
  • 用一个哈希表保存各个序列与对应交换次数。

2. 代码注解

  • int x = k / 3, y = k % 3;将一位数组的下标转换为二维数组。
  • swap(t[a * 3 + b], t[k]);交换两次的原因是:for 循环是遍历 t 的上下左右四个点,swap 一下意味着 x y 和 a b 两个点换了位置,t 现在是 a b 。判断完 a b 之后还要从 x y 出发去遍历其他三个点,所以要还原一下。
  • !d.count(t);是来判断这个点是否为有效点。因为要找到最短距离,要是不为零的话意味着用之前的换法已经换到这个状态过了,用现在这个状态接着换还不如接着以前的状态换,以前的步数还少一些,而且这样才能把所有可能换到的状态全部枚举一遍。

3. 实现代码

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

int bfs(string state)
{
    queue<string> q;
    unordered_map<string, int> d;

    q.push(state);
    d[state] = 0;

    int dx[4] = {-1, 0, 1, 0};
    int dy[4] = {0, 1, 0, -1};

    string end = "12345678x";
    while (q.size())
    {
        auto t = q.front();
        q.pop();

        if (t == end) 
        {
            return d[t];
        }

        int distance = d[t];
        int k = t.find('x');
        int x = k / 3, y = k % 3;
        for (int i = 0; i < 4; i ++ )
        {
            int a = x + dx[i];
            int b = y + dy[i];
            if (a >= 0 && a < 3 && b >= 0 && b < 3)
            {
                swap(t[a * 3 + b], t[k]);
                if (!d.count(t))
                {
                    d[t] = distance + 1;
                    q.push(t);
                }
                swap(t[a * 3 + b], t[k]);
            }
        }
    }

    return -1;
}

int main()
{
    char s[2];

    string state;
    for (int i = 0; i < 9; i ++ )
    {
        cin >> s;
        state += *s;
    }

    cout << bfs(state) << endl;

    return 0;
}

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

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

相关文章

iwebsec靶场 SQL注入漏洞通关笔记13-二次注入

系列文章目录 iwebsec靶场 SQL注入漏洞通关笔记1- 数字型注入_mooyuan的博客-CSDN博客 iwebsec靶场 SQL注入漏洞通关笔记2- 字符型注入&#xff08;宽字节注入&#xff09;_mooyuan的博客-CSDN博客 iwebsec靶场 SQL注入漏洞通关笔记3- bool注入&#xff08;布尔型盲注&#…

力扣(LeetCode)133. 克隆图(C++)

dfs哈希表图 先深搜建立所有点&#xff0c;加入哈希表。再遍历哈希表&#xff0c;按照拷贝前后的结点&#xff0c;拷贝边。最后返回某一结点&#xff0c;即为所求。 class Solution { public:unordered_map<Node*,Node*> mp;Node* cloneGraph(Node* node) {if(!node) r…

UNPV2 学习:Pipes and FIFOs 学习记录

命名管道 fifo 的特点 特点描述 打破了匿名管道只能在父子进程间使用的限制&#xff0c;可以在无亲缘关系的进程之间使用同一个 fifo未指定 NONBLOCK 参数 open fifo 时可能会 block&#xff0c;不当的编码可能会导致进程死锁当请求读超过 fifo 中现有数据大小的数据时&#…

基于yolov5轻量级的学生上课姿势检测识别分析系统

在我之前的博文中已经做过关于人体姿势识别人体姿态检测的博文&#xff0c;都是比较早期的技术模型了&#xff0c;随机技术的迭代更新&#xff0c;很多更加出色的模型陆续出现&#xff0c;这里基于一些比较好用的轻量级模型开发的姿态检测模型。 原始博文如下&#xff1a; 《…

HTML+CSS+JS家乡主题网页设计 学生网页设计作品 dreamweaver作业静态HTML网页设计模板 旅游景点网页作业制作

家乡旅游景点网页作业制作 网页代码运用了DIV盒子的使用方法&#xff0c;如盒子的嵌套、浮动、margin、border、background等属性的使用&#xff0c;外部大盒子设定居中&#xff0c;内部左中右布局&#xff0c;下方横向浮动排列&#xff0c;大学学习的前端知识点和布局方式都有…

BERT模型的详细介绍

Bert模型的基本原理是什么? BERT 来自 Google 的论文Pre-training of Deep Bidirectional Transformers for Language Understanding&#xff0c;BERT 是“Bidirectional Encoder Representations from Transformers”的首字母缩写&#xff0c;整体是一个自编码语言模型&…

全文检索-Elasticsearch-入门

文章目录前言一、基本概念1.1 Index&#xff08;索引&#xff09;1.2 Type&#xff08;类型&#xff09;1.3 Document&#xff08;文档&#xff09;1.4 ES与关系型数据库对比1.5 倒排索引二、初步检索2.1 _cat2.2 索引一个文档&#xff08;保存&#xff09;2.3 查询文档前言 全…

[静态时序分析简明教程(八)]虚假路径

静态时序分析简明教程-虚假路径一、写在前面1.1 快速导航链接二、虚假路径2.1 set_false_path2.2 -from -to -through2.3 上升/下降沿 约束2.4 建立/保持 约束2.5 虚假路径示例三、总结一、写在前面 一个数字芯片工程师的核心竞争力是什么&#xff1f;不同的工程师可能给出不同…

数据结构 | 堆的向上调整和向下调整算法【奇妙的堆排序】

堆一、堆的概念及结构二、向上调整算法⭐⭐1、算法思路分析【孙子的谋权篡位之旅&#x1f451;】2、代码详情解说三、向下调整算法⭐⭐⭐⭐⭐1、算法图解分析【高处不胜寒&#x1f192;趁早做打算】2、代码考究精析四、堆的数据结构各接口算法实现结构体的定义及声明1、堆的初始…

Windows-》CMD命令

CMD命令【1】Windows-》CMD命令1.mstsc&#xff1a;打开远程桌面连接。2.services.msc&#xff1a;打开本地服务设置。3.notepad&#xff1a;打开记事本。4.control&#xff1a;打开控制面板。5.regedit&#xff1a;打开注册列表编辑器。6.compmgmt.msc---设备管理器。&#xf…

[附源码]计算机毕业设计springboot医疗器械公司公告管理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

计算机图形学中的曲线问题——贝塞尔曲线的绘制

贝塞尔曲线的绘制 由于 CSDN 的博客修改字数的限制&#xff0c;我们不得不将这一部分放到一个新的博客中。原文详见&#xff1a; GGN_2015 计算机图形学中的曲线问题 贝塞尔曲线的几何作图法 在上面介绍儿时的回忆中&#xff0c;我们介绍了对于抛物线绘制的一种方法。如下图所…

Egg 1. 快速开始 Quick Start 1.3 一步步 Step by Step 1.3.5 创建服务

Egg Egg 本文仅用于学习记录&#xff0c;不存在任何商业用途&#xff0c;如侵删 文章目录Egg1. 快速开始 Quick Start1.3 一步步 Step by Step1.3.5 创建服务Hacker News API1. 快速开始 Quick Start 1.3 一步步 Step by Step 1.3.5 创建服务 在实际开发中&#xff0c;控制器…

[附源码]计算机毕业设计学生综合数据分析系统Springboot程序

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

Linux根文件系统说明和常用命令

Linux根文件系统说明【1】Linux内核由哪几个子系统组成&#xff1f;【2】Linux下软连接和硬链接的区别&#xff1f;【3】sync【4】shutdown –h now【5】shutdown –h 20:25【6】shutdown –r now【7】shutdown –r 10【8】reboot【9】halt【10】Linux根文件系统说明【11】此主…

机器学习 分类、回归、聚类、特征工程区别

一、分类和回归的区别 简单理解分类和回归的区别在于输出变量的类型不同。 定量输出称为回归&#xff0c;或者说是连续变量预测&#xff1b;定性输出称为分类&#xff0c;或者说是离散变量预测。 举个例子&#xff1a; 预测明天的气温是多少度&#xff0c;这是一个回归任务&…

AD入门学习—元件库(原理图库)的创建

目录 1.1 电阻类、电容类、电感类元件创建 1.2 LED灯、按键类元件创建 1.3 IC芯片类元件创建 学习目录 创建一个PCB工程&#xff0c;原理图库&#xff0c;原理图。 1.1 电阻类、电容类、电感类元件创建 左侧的菜单栏不见了:视图&#xff0c;panels&#xff0c;projects。 按…

JavaWeb(三)

前言&#xff1a;JavaWeb的三大组件Servlet&#xff0c;Filter&#xff0c;Listener。是Java EE Web服务规定的服务器动态组件&#xff0c;由开发者编写&#xff0c;由web容器创建&#xff0c;加载顺序为Listener->Filter->Servlet。 当来了一个application请求 呢么web三…

一文读懂Java中的String类之助力Java进阶之路

&#x1f51d;&#x1f51d;&#x1f51d;&#x1f51d;&#x1f51d;&#x1f51d;&#x1f51d;&#x1f51d;&#x1f51d;&#x1f51d;&#x1f51d;&#x1f51d;&#x1f51d;&#x1f51d;&#x1f51d; &#x1f947;博主昵称&#xff1a;Jovy. &#x1f35f;博客主页…

以太网 TCP协议(三次握手、四次挥手)

2.7.0 以太网 TCP协议&#xff08;三次握手、四次挥手&#xff09; 传输控制协议&#xff08;TCP&#xff0c;Transmission Control Protocol&#xff09;是一种面向连接的、可靠的传输层通信协议。 面向连接&#xff1a;指使用TCP协议的程序在使用的时候&#xff0c;需要预先进…