【C++算法】BFS解决多源最短路问题相关经典算法题

news2024/12/25 9:15:07

1.01矩阵

既然本章是BFS解决多源最短路问题,也就是说有若干个起点,那我们就可以暴力一点,直接把多源最短路径问题转化成若干个单源最短路径问题,然后将每次的步数比较一下,取到最短的就是最短路径的结果,这个想法好写,但是在本章都会超时,所以我们换一个思路:把所有的源点当成一个超级源点(包含所有的源点),那么问题就变成了单一的单源最短路径问题,此时我们使用一次bfs就可以解决问题。但是如何将这个源点当作一个超级源点呢?在解决单源最短路问题,我们的做法是把起点加入到队列,然后一层一层的往外扩展,所以我们只需要一开始将所有的起点都加入到队列,然后一层一层往外扩展即可,我们直接看第一个思路:

代码我已经替大家试过了,会超时,所以我们来看第二种思路:

直接上代码:

class Solution {
    int dx[4] = {0, 0, 1, -1};
    int dy[4] = {1, -1, 0, 0};
public:
    vector<vector<int>> updateMatrix(vector<vector<int>>& mat) {
        int m = mat.size();
        int n = mat[0].size();
        vector<vector<int>> dist(m, vector<int>(n, -1));

        // dist[i][j] == -1,表示:没有被搜索过
        // dist[i][j] != -1,表示:最短距离
        // 利用dist来直接标记该位置是否已经被使用
        queue<pair<int,int>> q;
        // 把所有为0的源点加入队列中
        for(int i = 0; i < m; i++)  
            for(int j = 0; j < n; j++)
                if(mat[i][j] == 0)
                {
                    q.push({i, j});
                    dist[i][j] = 0;
                }

        while(q.size())
        {
            // 此时我们不需要同时向外扩展
            // 因此不需要使用sz
            auto [a, b] = q.front();
            q.pop();
            for(int i = 0; i < 4; i++)
            {
                int x = a + dx[i], y = b + dy[i];
                if(x >= 0 && x < m && y >= 0 && y < n && dist[x][y] == -1)
                {
                    // 此时说明已经找到,直接修改dist的值即可
                    dist[x][y] = dist[a][b] + 1;
                    q.push({x, y});
                }
            }
        }
    return dist;
    }
};

2.飞地的数量

这道题目如果我们按照每次遍历数组每次遇到1就去bfs,肯定是会超时的,但是根据这个写法也有不超时的做法,我们遍历的时候,遇到1就去bfs,并将途中遇到1的位置标记一下,下一轮遇到1的时候,先dfs一下,如果这次dfs宽搜的时候遇到1,发现这个位置已经标记过,此时就不要bfs了,直接就是上次的结果,但是这样写需要两次dfs,并且dsf的代码还不一样,也比较麻烦,那我们来一个新思路:正难则反,我们可以从边上的 1 开始搜索,把与边上 1 相连的联通区域全部标记⼀下; 然后再遍历⼀遍矩阵,看看哪些位置的 1 没有被标记即可标记的时候,可以用「多源 bfs 」解决,bfs的逻辑和上一个题目基本差不多,直接上代码。

class Solution {
    int dx[4] = {0, 0, 1, -1};
    int dy[4] = {1, -1, 0, 0};
    bool vis[501][501] = {false};
public:
    int numEnclaves(vector<vector<int>>& grid) {
        int m = grid.size();
        int n = grid[0].size();
         // 1. 把边上的 1 加⼊到队列中
        queue<pair<int,int>> q;
        // 遍历行
        for(int i = 0; i < n; i++)
        {
            if(grid[0][i] == 1)
                q.push({0, i});
            if(grid[m - 1][i] == 1)
                q.push({m - 1, i});
        }
        // 遍历列
        for(int j = 0; j < m; j++)
        {
            if(grid[j][0] == 1)
                q.push({j, 0});
            if(grid[j][n - 1] == 1)
                q.push({j, n - 1});
        }
        // 2. 多源bfs
        while(q.size())
        {
            auto [a, b] = q.front();
            q.pop();
            vis[a][b] = true;
            for(int i = 0; i < 4; i++)
            {
                int x = a + dx[i];
                int y = b + dy[i];
                if(x >= 0 && x < m && y >= 0 && y < n && grid[x][y] == 1 && !vis[x][y])
                {
                    q.push({x, y});
                    vis[x][y] = true;
                }
            }
        }
        // 统计结果
        int ret = 0;
        for(int i = 0; i < m; i++)
            for(int j = 0; j < n; j++)
                if(grid[i][j] == 1 && !vis[i][j])
                    ret++;
        return ret;       
    }
};

3.地图中的最高点

注意本题给的是结果矩阵,我们可以先来看看原始矩阵的样子

此时就一目了然了,我们直接创建一个height数组,将isWater中的水域依次向外扩展,直接转化成多源bfs的问题,并且我们发现它就是01矩阵的变型题,直接上代码了:

class Solution {
    int dx[4] = { 0, 0, 1, -1 };
    int dy[4] = { 1, -1, 0, 0 };
public:
    vector<vector<int>> highestPeak(vector<vector<int>>& isWater) {
        int m = isWater.size();
        int n = isWater[0].size();
        // 数组不能初始化为0,因为数组中存在0 - 代表水域
        vector<vector<int>> height(m, vector<int>(n, -1));

        queue<pair<int, int>> q;
        // 把所有的源点加入到队列里面
        for (int i = 0; i < m; i++)
            for (int j = 0; j < n; j++)
                if (isWater[i][j] == 1)
                {
                    height[i][j] = 0;
                    q.push({ i,j });
                }
        // 多源bfs
        while (q.size())
        {
            auto [a, b] = q.front();
            q.pop();
            for (int i = 0; i < 4; i++)
            {
                int x = a + dx[i];
                int y = b + dy[i];
                // 该值没有被搜索过
                if (x >= 0 && x < m && y >= 0 && y < n && height[x][y] == -1)
                {
                    height[x][y] = height[a][b] + 1;
                    q.push({ x, y });
                }
            }
        }

        return height;
    }
};

4.地图分析

我们这个题目要求解海洋到陆地的最大距离,也可以求,但是海洋数量多蛮烦,正难则反,我们可以求陆地到海洋,将陆地作为超级源点依次向外扩展,随后创建一个dist数组,记录每次bfs的值保存在ist数组中即可解决,代码和上面的题目都相似,直接上代码:

class Solution
{
    int dx[4] = { 0, 0, 1, -1 };
    int dy[4] = { 1, -1, 0, 0 };
public:
    int maxDistance(vector<vector<int>>& grid)
    {
        int m = grid.size(), n = grid[0].size();
        vector<vector<int>> dist(m, vector<int>(n, -1));
        queue<pair<int, int>> q;
        for (int i = 0; i < m; i++)
            for (int j = 0; j < n; j++)
                if (grid[i][j] == 1)
                {
                    dist[i][j] = 0;
                    q.push({ i, j });
                }
        int ret = -1;
        while (q.size())
        {
            auto [a, b] = q.front(); q.pop();
            for (int i = 0; i < 4; i++)
            {
                int x = a + dx[i], y = b + dy[i];
                if (x >= 0 && x < m && y >= 0 && y < n && dist[x][y] == -1)
                {
                    dist[x][y] = dist[a][b] + 1;
                    q.push({ x, y });
                    ret = max(ret, dist[x][y]);
                }
            }
        }
        return ret;
    }
};

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

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

相关文章

安卓部署ffmpeg全平台so并实现命令行调用

安卓 FFmpeg系列 第一章 Ubuntu生成ffmpeg安卓全平台so 第二章 Windows生成ffmpeg安卓全平台so 第三章 生成支持x264的ffmpeg安卓全平台so 第四章 部署ffmpeg安卓全平台so并使用&#xff08;本章&#xff09; 文章目录 安卓 FFmpeg系列前言一、添加so1、拷贝ffmpeg到项目2、bu…

华为CE6851-48S6Q-HI升级设备版本及补丁

文章目录 升级前准备工作笔记本和交换机设备配置互联地址启用FTP设备访问FTP设备升级系统版本及补丁 升级前准备工作 使用MobaXterm远程工具连接设备&#xff0c;并作为FTP服务器准备升级所需的版本文件及补丁文件 笔记本和交换机设备配置互联地址 在交换机接口配置IP&#…

文件传输服务应用1——java集成smb2/3实现文件共享方案详细教程和windows共享服务使用配置

在实际项目开发过程中&#xff0c;读取网络资源或者局域网内主机的文件是必要的操作和需求。而FTP&#xff08;文件传输协议&#xff09;和SMB&#xff08;服务器消息块&#xff09;是两种最为常见的文件传输协议。它们各自在文件传输领域拥有独特的优势和特点&#xff0c;但同…

3DMax

先转换为可编辑多边形 按“1”选择为点&#xff0c;点击目标焊接&#xff08;CtrlShiftw&#xff09;&#xff0c;然后点击一个顶点拉到另一个定点上&#xff1b; 选择一个面&#xff0c;点击塌陷&#xff08;CtrlAltC&#xff09;&#xff0c;四点合并为一个点&#xff1b; …

Ai指令-公众号内训课:学会ai指令+公众号的底层逻辑(7节课)

课程目录 第一课:详解公众号的流量机制.mp4 第二课:快速搞定公众号号设化装修.mp4 第三课:一期学员直呼牛X的课程&#xff0c;正确的爆文利用姿势.mp4 第五课:颗粒度级别拆解AI公众号爆文.mp4 第六课:AI提示词进阶技巧课。提示词自动化.mp4 第七课.实操演示提示词撰写工作…

element-ui输入框和多行文字输入框字体不一样解决

element-ui的type"textarea"的字体样式与其他样式不同 <el-input type"textarea"></el-input> <el-input ></el-input>设置&#xff1a; .el-textarea__inner::placeholder {font-family: "Helvetica Neue", Helvetic…

GPIO模拟spi时序点亮数码管

目录 spi.h spi.c main.c 实验效果 spi.h #ifndef __SPI_H__ #define __SPI_H__#include "stm32mp1xx_gpio.h" #include "stm32mp1xx_rcc.h"//spi初始化 void spi_init(); //spi写入数据 void spi_write(unsigned char data);#endif spi.c #include…

C#编程-.NET Framework使用工具类简化对象之间的属性复制和操作

在C#编程中&#xff0c;对象之间的属性复制和操作是一个常见的需求。为此&#xff0c;.NET Framework提供了多种实用工具库&#xff0c;如AutoMapper、ValueInjecter和ExpressMapper。这些库通过简化代码&#xff0c;提高了开发效率。本文将介绍这些工具库&#xff0c;比较它们…

Html基础笔记

Html超文本标记语言 (HyperText Markup Language) 超文本 指的是网页中可以显示的内容(图片,超链接,视频,) 标记语言 标记–>标签(标注) 例如:买东西的时候—>商品具有标签,看到标签就知道商品的属性(价格,材质,型号等,) 标记语言就是提供了很多的标签,不同的标签…

Android 几个简单的自定义对话框介绍

Android 几个简单的自定义对话框介绍 文章目录 一、前言二、对话框相关内容1、效果2、对话框显示的调用代码&#xff08;1&#xff09;原生对话框代码&#xff1a;&#xff08;2&#xff09;自定义对话框代码&#xff1a; 3、对话框SweetAlertDialog 主要实现代码&#xff1a;4…

在DAYU200上实现OpenHarmony跳转拨号界面

一、简介 日常生活中&#xff0c;打电话是最常见的交流方式之一&#xff0c;那么如何在OpenAtom OpenHarmony&#xff08;简称“OpenHarmony”&#xff09;中进行电话服务相关的开发呢&#xff1f;今天我们可以一起来了解一下如何通过电话服务系统支持的API实现拨打电话的功能…

噱头还是风口?剖析AI短剧出海的未来

导语 |去年以来&#xff0c;低成本、高回报的土味短剧在国内爆火&#xff0c;而这股风也成功地刮到海外。2024 年&#xff0c;越来越多的人把目光投向了拥有庞大市场的国外“蓝海”&#xff0c;当人们还在高谈阔论 Sora 是否颠覆影视行业的时候&#xff0c;AI 已经在出海短剧中…

Linux系统搭建Tale个人博客网站并实现无公网IP访问本地博客

文章目录 前言1. Tale网站搭建1.1 检查本地环境1.2 部署Tale个人博客系统1.3 启动Tale服务1.4 访问博客地址 2. Linux安装Cpolar内网穿透3. 创建Tale博客公网地址4. 使用公网地址访问Tale 前言 今天给大家带来一款基于 Java 语言的轻量级博客开源项目——Tale&#xff0c;Tale…

【嵌入式芯片开发】不使用MicroLib的串口重定向万能预编译配置(适用于ARMCC、AC6等不同的编译器及版本)

【嵌入式芯片开发】不使用MicroLib的串口重定向万能预编译配置&#xff08;适用于ARMCC、AC6等不同的编译器及版本&#xff09; 文章目录 基本的串口重定向接收中断与scanf不能同时工作重定向卡死、低功耗一直唤醒 串口重定向万能预编译配置附录&#xff1a;Cortex-M架构的Sys…

【设计模式深度剖析】【5】【创建型】【原型模式】| 类比群发邮件,加深理解

&#x1f448;️上一篇:建造者模式 | 下一篇:创建型设计模式对比&#x1f449;️ 目录 原型模式(Prototype Pattern)概览定义英文原话直译 3个角色类图1. 抽象原型&#xff08;Prototype&#xff09;角色2. 具体原型&#xff08;Concrete Prototype&#xff09;角色3. 客户…

【cocos creator 】生成六边形地图

想要生成一个六边形组成的地图 完整代码示例 以下是完整的代码示例&#xff0c;包含了注释来解释每一步&#xff1a; cc.Class({extends: cc.Component,properties: {hexPrefab: {default: null,type: cc.Prefab},mapWidth: 10, // 网格的宽度&#xff08;六边形的数量&am…

基于Pytorch框架全连接神经网络对手势图片识别

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 文章目录 一项目简介 二、功能三、系统四. 总结 一项目简介 一、项目背景与意义 手势识别是计算机视觉领域的一个重要研究方向&#xff0c;具有广泛的应用前景&#xff0c;如人…

react中怎么为props设置默认值

在React中&#xff0c;你可以使用ES6的类属性&#xff08;class properties&#xff09;或者函数组件中的默认参数&#xff08;default parameters&#xff09;来定义props的默认值。 1.类组件中定义默认props 对于类组件&#xff0c;你可以在组件内部使用defaultProps属性来…

基于Java的推箱子游戏设计与实现(论文 + 源码)

【免费】关于基于JAVA的推箱子游戏.zip资源-CSDN文库https://download.csdn.net/download/JW_559/89325018 基于Java的推箱子游戏设计与实现 摘 要 社会在进步&#xff0c;人们生活质量也在日益提高。高强度的压力也接踵而来。社会中急需出现新的有效方式来缓解人们的压力。…

Java开发大厂面试第20讲:什么是分布式锁?Redi 怎样实现的分布式锁?

“锁”是我们实际工作和面试中无法避开的话题之一&#xff0c;正确使用锁可以保证高并发环境下程序的正确执行&#xff0c;也就是说只有使用锁才能保证多人同时访问时程序不会出现问题。 我们本课时的面试题是&#xff0c;什么是分布式锁&#xff1f;如何实现分布式锁&#xf…