第十三章 DFS与BFS(保姆级教学!!超级详细的图示!!)

news2024/9/29 9:38:53

第十三章 DFS与BFS

  • 一、深度优先搜索
    • 1、什么是DFS?
    • 2、DFS代码模板
      • (1)问题:
      • (2)分析:
      • (3)模板:
    • 3、DFS代码分析
  • 二、广度优先搜索
    • 1、什么是BFS?
    • 2、BFS代码模板
      • (1)问题:
      • (2)代码:
    • 3、BFS代码分析
      • (1)问题1:为什么要用队列?
      • (2)问题2:方向向量怎么用?
      • (3)问题3:为什么最后的输出是最短路?

一、深度优先搜索

1、什么是DFS?

DFS即Depth First Search,深度优先搜索。简单地理解为一条路走到黑。那么什么叫一条路走到黑呢?假设我们想在如下的地图中走出一条最长的路,那么最粗暴的方式就是枚举出每一种情况。
在这里插入图片描述
因此,按照DFS一条路走到黑的思想,我们将会出现如下路线:
在这里插入图片描述
先走A,然后到B,到了B有三种情况,意味着这条路还没走完,那我就接着走,从B走到E,走到E之后没路了。那我就回溯到B,为什么呢?
因为我原本走到B的时候就有三种情况,但是刚刚只走了一种情况,因此我要回到B再去尝试第二条路,于是我们就从E回到B,然后从B去F。到了F,又没路了,那我们就回到B走第三种情况,从B到G。这样我们就走完了从A->B的三种情况。又因为在A处其实还有三种情况,因此我们走完B的三种情况后,回到A,去走除了从A->B的第二种情况,即A->C。由此以往。

简而言之,就是我们一头扎进去,撞了南墙,我就退一步,但是决不放弃,在原基础上做出局部的改变去尝试第二条路,直到所有的情况我都试了,实在没有其他情况了,那我就回到A,从头出发,再做选择,再一头扎进去,直到成功。

2、DFS代码模板

(1)问题:

在这里插入图片描述

(2)分析:

在这里插入图片描述
我们将其各种选择,继续画成一棵树:
在这里插入图片描述
这张图就清晰很多了,因此想要用DFS,我们首先要有逻辑地画出一张地图,有了地图才能去搜。

(3)模板:

#include<iostream>
using namespace std;
const int N=10;
int ans[N];
bool mark[N];
int n;
void dfs(int u)
{
    //"回头"的条件
    if(u==n)
    {
        for(int i=0;i<n;i++)cout<<ans[i]<<" ";
        puts("");
        return;
    }
    
    for(int i=1;i<=n;i++)
    {
        if(mark[i]==false)
        {
            mark[i]=true;
            ans[u]=i;
            dfs(u+1);
            //复原
            mark[i]=false;
            ans[u]=0;
        }
    }
}

int main()
{
    cin>>n;
    dfs(0);
    return 0;
}

3、DFS代码分析

在这里插入图片描述
当然这个过程很抽象,那么我就帮大家模拟一下函数进行的过程吧^ _ ^(这里只模拟一部分,不理解的读者可自己模拟完。)
在这里插入图片描述

二、广度优先搜索

1、什么是BFS?

BFS即Breadth First Search,即广度优先搜索。如果说DFS是一条路走到黑的话,BFS就完全相反了。BFS会在每个岔路口都各向前走一步。因此其遍历顺序如下图所示:

在这里插入图片描述
我们发现每次搜索的位置都是距离当前节点最近的点。因此,BFS是具有最短路的性质的。为什么呢?这就类似于我们后面要学习的贪心策略。这里简单地介绍一下贪心,假设我们可以做出12次选择。我们想得到一个最好的方案。那么我们可以在第一次选择的时候,做出当前最好的选择,在第二次选择的时候,再做出那时候最好的选择,由此积累。当我们在每次的选择面前,都做到了当前最好的选择,那么我们就可以由局部最优推出整体最优。

这里也是类似的,我们可以在每次出发的时候,走到离自己最近的点,由此我们每次都保证走最近的,那从局部最近推整体最近,必有一条路是整体最近的。所以我们可以利用BFS做最短路问题。

2、BFS代码模板

(1)问题:

在这里插入图片描述
本题求的是最短路,因此我们可以利用BFS从当前节点出发,每次都向周围拓展。

(2)代码:

#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
const int N=110;
typedef pair<int,int> PII;
int map[N][N],mark[N][N];
int dx[4]={-1,0,1,0},dy[4]={0,1,0,-1},n,m,ans;
void bfs()
{
    memset(mark,-1,sizeof mark);
    queue<PII>q;
    q.push({0,0});
    mark[0][0]=0;
    while(!q.empty())
    {
        PII top=q.front();
        for(int i=0;i<4;i++)
        {
            int nex=top.first+dx[i],ney=top.second+dy[i];
            if(nex>=0&&nex<n&&ney>=0&&ney<m&&mark[nex][ney]==-1&&map[nex][ney]==0)
            {
                mark[nex][ney]=mark[top.first][top.second]+1;
                q.push({nex,ney});
            }
        }
        q.pop();
    }
    cout<<mark[n-1][m-1];
}
int main()
{
    cin>>n>>m;
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<m;j++)
        {
            scanf("%d",&map[i][j]);
        }
    }
    bfs();
}

3、BFS代码分析

在这里插入图片描述

(1)问题1:为什么要用队列?

BFS要保证的第一件事就是我们需要先走最近的,因此,队列的作用就是基于此的。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

(2)问题2:方向向量怎么用?

在这里插入图片描述
我们将上面的方向变化可以写成如下的数组:
在这里插入图片描述

(3)问题3:为什么最后的输出是最短路?

我们每个点都是同时向外拓展一步,并且只拓展一次。那么我们将其速度看作1步/次。每个点都向外探索一次。那么此时我们的次数可以类比为时间,由此每条路的速度和时间都是一样的,因此每条路的路程都是一样的。

而各个点都是从起点开始扩散的。我们看下面的例子:

在这里插入图片描述
某时刻,绿色线到达了B点,此时各个路线的长度都是L,那么接下来再走的话,蓝色线的路程和黄色线的路程只会更长,因此其再到达B点的时候,必不如绿色线近。== 因此,第一次到达某个点的路线,就是最短的路线 ==

由于mark数组中的点,踩过一次后,就不许再经过了。于是,我们惊奇地发现,每个点记录的路程都是从起点到该点的最短路!!!

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

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

相关文章

就是把一个数组中相同类别数据,组成新的数组

效果图如上&#xff0c;就是把一个数组中相同类别数据&#xff0c;组成新的数组&#xff0c;每个数组最后加一个空对象&#xff0c;对象对应的格式要做些许改变 分店 品牌 业绩(元) 订单个数 单值(元) {{item.shopname}} {{item.shopname}} {{item.shopname}} {{item.shopname}…

《InnoDB引擎九》InnoDB关键特性-自适应哈希索引

InnoDB 关键特性 InnoDB存储引擎的关键特性包括&#xff1a; Insert Buffer (插入缓冲)Double Write (两次写)Adaptive Hash Index (自适应哈希索引)Async IO (异步IO)Flush Neighbor Page (刷新领接页) 这些特性为InnoDB存储引擎带来了更好的性能以及更高的可靠性。 自适应哈…

猿如意开发工具|emeditor

写在前面 昨天升了下系统&#xff0c;可以下载了&#xff0c;我就试了试 正文 在客户端里搜索我所需要的工具&#xff0c;就可以搜出来 这里我已经下好了&#xff0c;直接点开文件就好了 再点开文件 点击下一步&#xff0c;接下来还有几个步骤&#xff0c;都点下一步就可以了…

【HBuilder X】解决HBuilder X内置浏览器显示过大影响使用

1- 前言 不知道宝子们有没有遇到过这种情况&#xff0c;小媛发现自己的内置浏览器过大&#xff0c;很大&#xff0c;很丑&#xff0c;占了半个屏幕&#xff0c;像下图那样。 也试了几种方法&#xff0c;比如&#xff1a; 看自己的版本不是最新&#xff0c;或者和其他人的不一样…

嫁给程序员老公,我后悔了

01 在我还没长开的时候&#xff0c;就常听人说&#xff0c;有两种男人不能嫁&#xff1a;一种是兵哥哥&#xff0c;另一种是程序员。前者见不着&#xff0c;后者死的早。 一想到不等头发花白&#xff0c;就要踟蹰独行&#xff0c;我就害怕的厉害。所以&#xff0c;很长一段时…

2023最新SSM计算机毕业设计选题大全(附源码+LW)之java高校教室管理系统9y8cv

相信很多和我一样的同学&#xff0c;因为实习&#xff0c;因为考研和考公等等&#xff0c;来不及做毕业设计&#xff0c;双专业的话 到时肯定忙不过来。提前做好准备吧&#xff0c;能自己完成的尽量自己完成&#xff0c;尽量不要找别人。自己的毕业前的一次大作业。努力完成也有…

Java项目:ssm高校党员管理系统

作者主页&#xff1a;源码空间站2022 简介&#xff1a;Java领域优质创作者、Java项目、学习资料、技术互助 文末获取源码 项目介绍 高校党员信息管理系统&#xff0c;分为普通用户和管理员两种角色。 普通用户登录后主要功能有&#xff1a; 我的中心:首页、个人资料、修改密…

广州蓝景分享—开发人员都知道的JavaScript技巧

JavaScript包含各种对典型编程思想有用的一些技巧&#xff0c;在实际开发中&#xff0c;我们通常希望减少代码行数&#xff1b;因此&#xff0c;今天这些技巧代码希望可以帮助到你。 现在我们就开始今天的内容吧。 1、与Javascript对象相关的 01)、对象解构 将对象的值解构为…

Vue2.0简讲!

Vue2.0简讲 Draven入门1.1、响应式渲染1.1.0、Vue创建1.1.1、指令(7)1.1.2、class与style绑定HTML Class对象语法数组语法绑定内联样式对象语法数组语法1.1.3、条件渲染v-if else-iftemplate v-if1.1.4、列表渲染v-forkey数组更新检测列表渲染Vue2列表渲染Vue3过滤应用(模糊查询…

机器学习与数据挖掘——前言

如果有兴趣了解更多相关内容&#xff0c;欢迎来我的个人网站看看&#xff1a;瞳孔空间 这是从老师的PPT里面提取出来的&#xff0c;知识点分布比较零散&#xff0c;可能他做PPT的时候也没想那么多。 一&#xff1a;机器学习 机器学习的定义&#xff1a;一个计算机程序被称为…

前端岗位初入职场后的最初一段时间需要做什么

文章题目有点长&#xff0c;叫 《前端岗位初入职场后的最初一段时间需要做什么》&#xff0c;说下写这篇文的初衷&#xff0c;在前端自学团里有很多刚毕业或者是刚从培训班出来的同学&#xff0c;在群里天天讨论着找工作和面试的事情&#xff0c;面试的题在很多app或者小程序可…

四、【React-Router6】高亮 NavLink

项目修改自 上一节 的 Demo 这里需要注意的变化 默认高亮样式类名如果依然是 active 则依然默认有效 6 里移除了 activeClassName &#xff0c;如果我的高亮样式类名是 peiqi&#xff0c;需要配置 className 为一个函数 函数接收两个参数 isActive&#xff1a;是否激活isPendi…

Arduino开发实例-DIY双向访客计数器和自动灯光控制

双向访客计数器和自动灯光控制 1、应用介绍 本应用将使用 Arduino 创建双向访客柜台和自动灯光控制系统。该应用基于一对 IR(红外)传感器,可在出现中断时检测障碍物。实际上,该系统可以检测来自两个方向的访客。从而对进入的访客数量和离开的访客数量进行计数。 该双向访…

2023最新SSM计算机毕业设计选题大全(附源码+LW)之java高校心理健康咨询平台vknhv

毕业设计其实不难&#xff0c;主要毕业的时候任务太紧了&#xff0c;所以大家都非常忙没有时间去做&#xff0c;毕业设计还是早做准备比较好&#xff0c;多花点时间也可以做出来的&#xff0c;建议还是自己动手去做&#xff0c;比如先选一个题&#xff0c;这样就有方向&#xf…

GIS工具maptalks开发手册(三)01——绘制工具

GIS工具maptalks开发手册(三)01——绘制工具 效果 代码 1、html官方版 <!DOCTYPE html> <html> <meta charset"UTF-8"> <meta name"viewport" content"widthdevice-width, initial-scale1"> <title>交互 - 绘制…

vite + vue3.0 + ts 项目搭建

Welcome to vue3-elementplus-admin &#x1f44b; vite vue3 Pinia elementUi-plus 无限级菜单 权限管理 后台模板 &#x1f3e0; Homepage Author &#x1f464; xuxuxu-ni Github: xuxuxu-niQQ: 595485548QQ群: 157216616email: 595485548qq.com Prerequisites node…

安卓使用动画启动Acitvity

1.检查系统版本 动画过渡Activity适用于*Android5.0&#xff08;API21&#xff09;*及以上&#xff0c;在代码增加中检查版本增强代码健壮性。 2.指定自定义过渡动画。 过渡可以在xml文件中指定&#xff0c;也可以直接在代码中指定。使用Window.requestFeature()声明启动窗口…

C语言:结构体

1、结构体&#xff1a; 定义&#xff1a;结构是一些值的集合&#xff0c;这些值称为成员变量。结构的每个成员可以是不同类型的变量 结构的声明&#xff1a; struct tag {member-list;}variable-list;举例&#xff1a;声明一个学生类型&#xff0c;想通过学生类型来创建学生变…

【Matplotlib绘制图像大全】(二十七):Matplotlib将数组array保存为图像

前言 大家好,我是阿光。 本专栏整理了《Matplotlib绘制图像大全》,内包含了各种常见的绘图方法,以及Matplotlib各种内置函数的使用方法,帮助我们快速便捷的绘制出数据图像。 正在更新中~ ✨ 🚨 我的项目环境: 平台:Windows10语言环境:python3.7编译器:PyCharmMatp…

SpringBoot+Vue实现前后端分离的大学生志愿者管理系统

文末获取源码 开发语言&#xff1a;Java 使用框架&#xff1a;spring boot 前端技术&#xff1a;JavaScript、Vue.js 、css3 开发工具&#xff1a;IDEA/MyEclipse/Eclipse、Visual Studio Code 数据库&#xff1a;MySQL 5.7/8.0 数据库管理工具&#xff1a;phpstudy/Navicat JD…