代码随想录算法训练营第四十天| 深搜与广搜理论基础以及模板代码

news2024/9/22 13:34:18

今天是算法学习第四十天,主要的学习内容是深度优先搜索和广度优先搜索,以及对于模板题的讲解。

深度优先搜索(DFS)

深搜其实原理就是先往一个方向搜索,直到遇到终止条件再回头。所以深度优先搜索的关键就是递归和回溯。

对于深搜代码的模板,其实和回溯是很相似的。我们首先确定递归函数的参数和返回值,然后确定递归函数的终止条件,最后确认对当前节点的处理方式。具体框架如下所示:

void dfs(参数) {
    if (终止条件) {
        存放结果;
        return;
    }

    for (选择:本节点所连接的其他节点) {
        处理节点;
        dfs(图,选择的节点); // 递归
        回溯,撤销处理结果
    }
}

广度优先搜索(BFS) 

广度优先搜索的思路是以起始点为中心一圈一圈地进行搜索,一旦遇到终点,记录之前走过的节点就是一条最短路。所以,广搜适合解决两个点之间的最短路径问题。

对于广度优先搜索的代码实现,一般是使用队列这一数据结构进行实现。模板代码如下所示:

int dir[4][2] = {0, 1, 1, 0, -1, 0, 0, -1}; // 表示四个方向
// grid 是地图,也就是一个二维数组
// visited标记访问过的节点,不要重复访问
// x,y 表示开始搜索节点的下标
void bfs(vector<vector<char>>& grid, vector<vector<bool>>& visited, int x, int y) {
    queue<pair<int, int>> que; // 定义队列
    que.push({x, y}); // 起始节点加入队列
    visited[x][y] = true; // 只要加入队列,立刻标记为访问过的节点
    while(!que.empty()) { // 开始遍历队列里的元素
        pair<int ,int> cur = que.front(); que.pop(); // 从队列取元素
        int curx = cur.first;
        int cury = cur.second; // 当前节点坐标
        for (int i = 0; i < 4; i++) { // 开始想当前节点的四个方向左右上下去遍历
            int nextx = curx + dir[i][0];
            int nexty = cury + dir[i][1]; // 获取周边四个方向的坐标
            if (nextx < 0 || nextx >= grid.size() || nexty < 0 || nexty >= grid[0].size()) continue;  // 坐标越界了,直接跳过
            if (!visited[nextx][nexty]) { // 如果节点没被访问过
                que.push({nextx, nexty});  // 队列添加该节点为下一轮要遍历的节点
                visited[nextx][nexty] = true; // 只要加入队列立刻标记,避免重复访问
            }
        }
    }

}

99. 岛屿数量

题目链接:99. 岛屿数量 (kamacoder.com)

这个题目使用深搜和广搜都可以解决。我们先聊一聊深搜的做法,其实就是往四周进行遍历,由于这是一个无向图,为了防止回环的情况,我们需要设置一个数组用来存储每个点是否走过。具体代码实现如下所示:
 

#include<iostream>
#include<vector>
using namespace std;
int dis[4][2]={0,1,1,0,-1,0,0,-1};
void dfs(vector<vector<int>> &graph,vector<vector<bool>> &visited,int x,int y)
{
    if(visited[x][y]==1||graph[x][y]==0) return;
    visited[x][y]=1;
    for(int i=0;i<4;i++)
    {
        int nextx=x+dis[i][0];
        int nexty=y+dis[i][1];
        if(nextx<0||nexty<0||nextx>=graph.size()||nexty>=graph[0].size()) continue;
        dfs(graph,visited,nextx,nexty);
    }
}
int main()
{
    int m,n;
    scanf("%d %d",&m,&n);
    vector<vector<int>> graph(m+1,vector<int>(n+1,0));
    for(int i=0;i<m;i++)
    {
        for(int j=0;j<n;j++)
        {
            scanf("%d",&graph[i][j]);
        }
    }
    vector<vector<bool>> visited(m+1,vector<bool>(n+1,false));
    int result=0;
    for(int i=0;i<m;i++)
    {
        for(int j=0;j<n;j++)
        {
            if(!visited[i][j]&&graph[i][j]==1)
            {
                result++;
                dfs(graph,visited,i,j);
            }
             
        }
    }
    cout<<result;
}

除此之外,广搜也可以解决这个题目。需要注意的是,广搜代码一般需要在内部判断节点的可达性,并将存储遍历情况的数组赋值为1.这样可以有效降低时间复杂度。具体代码实现如下所示:
 

#include<iostream>
#include<queue>
#include<vector>
using namespace std;
int dis[4][2]={0,1,1,0,-1,0,0,-1};
void bfs(vector<vector<int>> &graph,vector<vector<bool>> &isvisited,int x,int y)
{
     
    queue<pair<int,int>> que;
    que.push({x,y});
    while(!que.empty())
    {
        pair<int,int> point=que.front();
        que.pop();
        for(int i=0;i<4;i++)
        {
            int nextx=point.first+dis[i][0];
            int nexty=point.second+dis[i][1];
            if(nextx<0||nexty<0||nextx>=graph.size()||nexty>=graph[0].size()) continue;
            if(isvisited[nextx][nexty]==0&&graph[nextx][nexty]==1)
            {
                que.push({nextx,nexty});
                isvisited[nextx][nexty]=1;
            }
        }
    }
}
int main()
{
    int m,n;
    cin>>m>>n;
    vector<vector<int>> graph(m+1,vector<int>(n+1,0));
    vector<vector<bool>> isvisited(m+1,vector<bool>(n+1,0));
    for(int i=0;i<m;i++)
    {
        for(int j=0;j<n;j++)
        {
            scanf("%d",&graph[i][j]);
        }
    }
    int result=0;
    for(int i=0;i<m;i++)
    {
        for(int j=0;j<n;j++)
        {
            if(isvisited[i][j]==0&&graph[i][j]==1) 
            {
                result++;
                bfs(graph,isvisited,i,j);
            }
        }
    }
    printf("%d\n",result);
}

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

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

相关文章

超声波清洗机哪个品牌好用?实用性强的超声波眼镜清洗机推荐

眼镜一类的物品都很难清理&#xff0c;特别容易刮花&#xff0c;此外还有小件的首饰&#xff0c;也很难通过常规的清洁方式去除污渍&#xff0c;这时候就要用到超声波清洗机&#xff0c;这两年这种小工具很流行&#xff0c;而超声波清洗机便是其中的一种热门清洁神器&#xff0…

Kafka命令详解:从零开始,掌握Kafka集群管理、主题操作与监控的全方位技能,理解每一条命令背后的逻辑与最佳实践

本文主要是关于Kafka的命令详解&#xff0c;每个命令都进行了非常详细的注释&#xff0c;帮助大家能更好的理解这些命令背后的含义&#xff0c;从底层去理解&#xff0c;如果大家喜欢&#xff0c;请多多点赞关注&#xff0c;欢迎评论&#xff01; 为大家推荐几篇比较好的Kafka文…

【selenium点选下拉框】解决无法选中对应选项的问题

需求 使用selenium点击下拉框&#xff0c;选中【是】选项。 代码 方法1 # 点击下拉框 driver.find_element(xpath,//*[id"basicProcessDetail"]/div[2]/div[2]/div[1]/div/div[2]/div/div/div/div[1]/div[2]/form/div[11]/div[1]/div/div/div[1]/div[1]/div/i).…

扫描件转word如何操作?分享3个转换技巧,简单高效

在日常工作中&#xff0c;总会遇到扫描件格式的PDF文档&#xff0c;为了方便整理&#xff0c;修改和使用&#xff0c;我们经常需要将扫描件转成可编辑的Word文档&#xff0c;那有哪些方法可以将扫描件转换成Word呢&#xff1f;本期小编就给大家分享3个转换技巧&#xff0c;简单…

mysql索引的基本原理

1.索引的基本原理 是为了提高数据检索效率&#xff0c;通过排列好的数据结构&#xff08;通常是二叉树或B-Tree&#xff09;来加快查找过程。1.1 优势 是帮助mysql获取数据的一种高效数据结构&#xff0c;并且是有序的&#xff1b;提高数据的检索效率&#xff0c;降低数据库的…

用IP地址申请SSL证书可行吗?

在当今社会&#xff0c;互联网的安全非常重要&#xff0c;SSL&#xff08;Secure Sockets Layer&#xff09;证书作为保障网站安全的重要工具&#xff0c;能够加密网站与用户之间的数据传输&#xff0c;保护用户隐私&#xff0c;提升网站信任度等。然而&#xff0c;传统的SSL证…

【计算机组成原理】四、指令系统:3.汇编语言

5.汇编语言 文章目录 5.汇编语言5.1考试要求&#xff08;408&#xff09;x86汇编语言5.2地址码x86架构CPU&#xff0c;有哪些寄存器&#xff1f;总结 5.3操作码5.3.1算术运算5.3.2逻辑运算5.3.3其他 5.4循环分支5.4.1 jmp直接跳转指令5.4.2 jxxx条件跳转指令分支C→汇编循环C→…

Openstack 与 Ceph集群搭建(下): Openstack部署

文章目录 文章参考部署节点准备1. 修改Host文件与hostname名称2. 安装NTP软件3. 网卡配置信息4. 开启Docker共享挂载5. 安装python虚拟环境6. 安装kolla-ansible7. 加载Ansible galaxy requirements Openstack 安装前预配置1. 配置密码2. 配置multinode文件3. 修改全局配置文件…

2.Easy-Paas部署

目录 1.部署方式 2.docker-compose部署 1.1.准备docker环境 1.2.部署中间件 3.k8s部署 1.部署方式 docker-compose部署&#xff08;单节点&#xff09;k8s部署自研ops 2.docker-compose部署 1.1.准备docker环境 参考&#xff1a;二进制安装docker-CSDN博客 1.2.部署中…

安科瑞储能双向计量表DTSD1352-CT/CF 双向电量复费率统计

安科瑞徐赟杰 Hey科技迷们&#xff0c;你们是否对能源管理的新纪元充满好奇&#xff1f; 今天咱们来聊聊这款颠覆性的黑科技——安科瑞储能双向计量表DTSD1352&#xff01; 想象一下&#xff0c;一个能够掌控能量流动&#xff0c;无论是输入还是输出&#xff0c;都了如指掌的…

Thread类的基本用法(详解版)

什么是线程&#xff1f; 线程是操作系统能够进行调度的最小单位&#xff0c;通常被视为轻量级的进程。线程在同一进程中共享进程的资源&#xff08;如内存&#xff0c;打开的文件&#xff0c;网络等&#xff09;&#xff0c;但每一个线程都有自己的执行栈、程序计数器和局部变…

项目管理中什么是项目质量管理?

所有项目经理都易于犯下的通病便是产生无谓的乐观&#xff0c;误以为质量会自然而然地融入项目之中。然而&#xff0c;在实际操作中&#xff0c;我们必须明确界定、监控并管理项目管理质量。 项目质量管理的核心在于确保项目质量。这被称为项目的第四个约束&#xff0c;经理们必…

澄志创投马良骏:营销技术行业下一个关键词是合并与整合 | 中国广告营销行业资本报告深访①

日前&#xff0c;澄志创投发布了《中国广告营销行业资本报告2022》&#xff0c;投中信息提供独家数据支持&#xff0c;Marteker联合撰写。报告围绕广告营销行业的资本运作等话题&#xff0c;采访了行业资深人士。 马良骏Joshua&#xff08;澄志创投创始人&#xff09; 问&#…

Module not found: Can‘t resolve ‘tls‘/Module not found: Can‘t resolve ‘net‘

最近使用nextjs开发了一套系统&#xff0c;包含了前后端&#xff0c;但是前后端的界限其实没有那么清晰&#xff0c;很多地方都引入了公共的内容&#xff0c;甚至互相引入了其模块的内容 然后周五时在前端引入了一个方法&#xff08;该方法在前端的模块里面定义的&#xff0c;之…

【Linux】基本命令(第二篇)

目录 1.命令提示符 2.命令的基本格式 1) 选项的作用 2) 参数的作用 2.cd命令&#xff1a;切换目录 3.pwd命令&#xff1a;显示当前路径 4.ls命令&#xff1a;查看目录下文件 5.mkdir命令&#xff1a;创建目录&#xff08;文件夹&#xff09; 6.rmdir命令&#xff1a;删…

《黑神话:悟空》横空出世:全新国产3A里程碑之作

“直面天命”、“棒打虎先锋”、“猿神&#xff0c;启动”......在过去的一周里&#xff0c;从朋友圈到微博热搜&#xff0c;从咖啡联名到陕西文旅&#xff0c;几乎已经没有人&#xff0c;可以对《黑神话&#xff1a;悟空》这一国产3A里程碑之作视而不见。8月20日上午10时&…

eclipse汉化教程

1:选择HELP->install New software 2:点击Add 3&#xff1a;name随便填写&#xff0c;location&#xff1a;https://download.eclipse.org/technology/babel/update-site/latest/ 4&#xff1a;等待下载完成后点next 5&#xff1a;选择中文&#xff0c;再点击next 6. 等待…

【实战】Spring Boot 嵌套事务REQUIRES_NEW与NESTED在项目中的运用

文章目录 引言1. 什么是Nested Transactions?2. Spring Boot中的事务管理2.1 基本用法2.2 Nested Transactions的需求场景 3. 实现Nested Transactions3.1 使用Propagation.REQUIRED)/Propagation.NESTED)3.2 嵌套事务REQUIRES_NEW与NESTED3.3 注意事项 4. 测试Nested Transac…

upload-labs(Pass-18 ~ Pass-21)

1、Pass-18(条件竞争) 1、题目需要进行代码审计&#xff1a; <?php include ../config.php; include ../head.php; include ../menu.php;$is_upload false; $msg null;if(isset($_POST[submit])){$ext_arr array(jpg,png,gif);//白名单$file_name $_FILES[upload_fil…

OpenLayers3,地图探查功能实现

文章目录 一、前言二、代码实现三、总结 一、前言 图层探查&#xff0c;即对置于地图下方的图层进行一定范围的探查&#xff0c;以便用户查看到不易察觉的地理地况。本文基于OpenLayers3&#xff0c;实现地图探查的功能。 二、代码实现 <!DOCTYPE HTML PUBLIC "-//W…