【基础算法总结】多源 BFS_多源最短路问题

多源 BFS_多源最短路问题

  • 1.多源 BFS_多源最短路问题
  • 2.01 矩阵
  • 3.飞地的数量
  • 4.地图中的最高点
  • 5.地图分析

在这里插入图片描述

点赞👍👍收藏🌟🌟关注💖💖
你的支持是对我最大的鼓励,我们一起努力吧!😃😃

1.多源 BFS_多源最短路问题

最短路径问题有单源最短路径、多源最短路径、边权为 1 的最短路径、带负环的最短路等等。目前我们学了,边权为 1 的最短路径。

单源最短路径

前面一个专题用BFS 解决 边权为 1 的最短路径问题,都是单源最短路径问题。

一个起点一个终点 求最短路径
在这里插入图片描述

多源最短路径

多个起点一个终点 求从多个起点出发到终点的最短路径问题。
在这里插入图片描述

多源 BFS

用 BFS 解决边权为 1 的多源最短路径问题。

不管是单源还是多源只要用 BFS 解决边权都是为1的。边权是其他的是不能用BFS解决。也就是只要是用BFS解决最短路径问题,必须都是边权为1 !

如何解决?

解法一:暴力,把多源最短路径问题转化成若干个单源最短路径问题

也就是说给我若干个起点,用BFS暴力枚举出所有起点到终点的最短路径,然后取其中最短的路径。大概率是会超时的。

解法二:把所有的源点当成一个 超级源点,问题就变成了单一的单源最短路径问题

意思就是给我很多起点,我想办法把这些起点当成一个起点,问题就变长了从这一个超级起点开始到终点的最短路径了。仅需从这个超级起点出发来一次BFS就可以了。

在这里插入图片描述

这里可能会有疑惑,把所有起点当成一个超级起点出发最终得到的路径是正确答案吗?

这里我们感性的理解一下,所有起点的小人同时向外走一步。它们同时向外走一步,我们是可以舍去很多点的。比如有的起点小人向外走一步但是这一步已经被其他小人走过了,所以说从这个点向外走一步肯定没有其他点向外走一步更好,因此就可以舍去这个点。然后就相当于从超级起点出发向外走一步。把不好的都舍去只把好的保留,这就是超级源点干的事情。因为只保留好的,所以到达某一点绝对是最短的。

在这里插入图片描述

如何写代码呢?

这里的重点就是如何把所有起点搞成一个超级起点呢?特别简单,我们回忆一下 边权为1 单源最短路径问题 用 BFS 怎么解决,分为两步:

  1. 把起点加入到队列
  2. 一层一层往外扩

如何把所有起点搞成一个超级起点呢?

  1. 把所有起点加入到队列
  2. 一层一层往外扩

2.01 矩阵

题目链接: 542. 01 矩阵

题目分析:
在这里插入图片描述

给一个m*n的矩阵mat,返回一个同等大小的矩阵并且矩阵中每个格子都是到达0的最短距离。

在这里插入图片描述

算法原理:

解法一:一个位置一个位置求

遍历一下矩阵,一个一个位置BFS求到0的最短距离,但是会超时。

解法二:多源BFS + 正难则反

我们可以把所有的1当成一个超级起点,然后从这个起点做一次BFS,但是如果把1作为起点有一个致命问题,你更新不出来结果,把1当成超级起点从1找到0之后那是那个1到达的0?并且又如何回到开始位置去更新1到0的最短距离呢?

正着来起点到终点最短距离,那反着来终点到起点最短距离也是没问题的。所以,把所有的 0 当成起点,1 当成终点,当扩展到1的时候直接把距离更新到对应1的位置就行了。

  1. 把所有的 0 位置加入到队列中
  2. 一层一层的向外扩即可

刚开始遍历一下把所有0加入到队列中同时也把dist中对应位置更新成0,然后一层一层往外扩,我们是把队列中元素拿出来上下左右四个方向像外扩。当层序遍历结束之后这个dist也就填完了。把dist返回就可以了。

在这里插入图片描述

这里有一些细节问题:

回忆求边权为 1 的单源最短路径,我们写代码时是需要一个bool类型vis二维数组标记当前位置是否被搜索过,并且层序遍历中还需要step记录当前扩展到那一层,sz记录当前队列中的元素是把队列中所有元素都往外扩一层,结合step知道当前扩展到这一层的步数是多少。

这道题我们仅需一个dist二维数组就行了,不需要上面三个东西。先看这个bool数组,其实我们可以把dist数组里面的值全部都初始化-1来标记当前位置没有被搜索过。step和sz也不用要,我们直接从dist数组中就可以更新下一个位置中dist的值,之前是从[a,b] 上下左右扩展 [x,y],这次从[a,b] 扩展到 [x,y] dist中已经记录[a,b]位置的值了,仅需dist[x][y] = dist[a][b] + 1 即可。而且也不用搞一个sz一层一层往外扩,我们可以一个元素一个元素往下扩,原因就是dist已经标记当前元素是处于那一层的。

在这里插入图片描述

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(), n = mat[0].size();// dist[i][j] == -1 表⽰:没有搜索过// dist[i][j] != -1 表⽰:最短距离vector<vector<int>> dist(m,vector<int>(n,-1));queue<pair<int,int>> q;// 1. 把所有的源点加⼊到队列中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;}// 2. ⼀层⼀层的往外扩 (因为dist每个起点的开始层数了,因此不用再搞一个sz)while(q.size()){auto [a,b] = q.front();q.pop();for(int k = 0; k < 4; ++k){int x = a + dx[k], y = b + dy[k];if(x >= 0 && x < m && y >= 0 && y < n && dict[x][y] == -1){dict[x][y] = dict[a][b] + 1;q.push({x,y});}}            }return dist;}
};

3.飞地的数量

题目链接: 1020. 飞地的数量

题目分析:

在这里插入图片描述

返回矩阵中无法通过边界离开网格的陆地的数量。

算法原理:

解法一:一个一个去判断
遍历矩阵当遇到一个1的时候就去判断能不能走出去。时间复杂度很恐怖。

但是可以一个一个去判断做一些优化,当遇到一个1的时候先做一次BFS看与这个1相连的连通块能不能到边界,如果能的话,然后再来一次BFS统计1的个数并且标记一下该位置已经被搜索过,如果不能的话把这块地方标记为0。需要写两份不同的BFS代码。

解法二:多源BFS + 正难则反

我不判断1这个位置能不能走到边界,而是判断边界上的1能不能走到你。把所有边界1当作一个超级起点向内搜索,把搜索到的1都标记一下表明这些位置都是能走出去的。最后再搜索一下看看那些1是没被标记过的统计一下就是答案。

在这里插入图片描述

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

4.地图中的最高点

题目链接: 1765. 地图中的最高点

题目分析:

在这里插入图片描述

给一个m*n的矩阵,格子里面0代表陆地,1代表水域。

按照下面要去给每个格子安排高度:

每个格子的高度都必须是非负的。

如果一个格子是 水域 ,那么它的高度必须为 0

任意相邻的格子高度差 至多 为 1 。当两个格子在正东、南、西、北方向上相互紧挨着,就称它们为相邻的格子。(也就是说它们有一条公共边)

找到一种安排高度的方案,使得矩阵中的最高高度值 最大

算法原理:

按照上面的要求,我们可以先安排水域,如果你安排其他地方,它要受它上下左右的控制才行不能随意给一个数。将所有水域变成0然后按照多源BFS走一次就行了。因为要求高度值最大,因此每个临近位置都+1往外扩。这里和前面一道题几乎一模一样。

在这里插入图片描述

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(), n = isWater[0].size();vector<vector<int>> dist(m , vector<int>(n, -1));queue<pair<int,int>> q;// 1. 把所有的源点加⼊到队列⾥⾯for(int i = 0; i < m; ++i)for(int j = 0; j < n; ++j)if(isWater[i][j] == 1){q.push({i,j});dist[i][j] = 0;}// 2. 多源 bfswhile(q.size()){auto [a,b] = q.front();q.pop();for(int k = 0; k < 4; ++k){int x = a + dx[k], y = b + dy[k];if(x >= 0 && x < m && y >= 0 && y < n && dist[x][y] == -1){dist[x][y] = dist[a][b] + 1;q.push({x,y});}}}return dist;}
};

5.地图分析

题目链接: 1162. 地图分析

题目分析:

在这里插入图片描述

给一个 n x n 的 网格 grid,上面的每个 单元格 都用 0 和 1 标记好了。其中 0 代表海洋,1 代表陆地。

找出一个海洋单元格,这个海洋单元格到离它最近的陆地单元格的距离是最大的,并返回该距离。如果网格上只有陆地或者海洋,请返回 -1。

「曼哈顿距离」( Manhattan Distance):(x0, y0) 和 (x1, y1) 这两个单元格之间的距离是 |x0 - x1| + |y0 - y1| 。其实就是最短路径

在这里插入图片描述

算法原理:

解法: 多源BFS + 正难则反

从海洋找陆地不好搞路径,反过来从陆地到海洋。陆地初始为0。

在这里插入图片描述

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){q.push({i,j});dist[i][j] = 0;}int ret = -1;while(q.size()){auto [a,b] = q.front();q.pop();for(int k = 0; k < 4; ++k){int x = a + dx[k], y = b + dy[k];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.rhkb.cn/news/406319.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

NtripShare全站仪自动化监测之气象改正

最近有幸和自动化监测领域权威专家进行交流&#xff0c;讨论到全站仪气象改正的问题&#xff0c;因为有些观点与专家不太一致&#xff0c;所以再次温习了一下全站仪气象改正的技术细节。 气象改正的概念 全站仪一般利用光波进行测距&#xff0c;首先仪器会处理测距光波的相位漂…

SpingBoot 两种方式配置多数据源

第一种&#xff1a;使用与MyBaits-Plus师出同门的“dynamic-datasource-spring-boot-starter” 官网地址&#xff1a; 基础必读&#xff08;免费&#xff09; dynamic-datasource 看云 1&#xff1a;引入依赖 <!-- 苞米豆多数据源 --> <dependency><group…

科技大厂对AI的垄断

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

ios白苹果修复办法有哪些?

在这个数字化时代&#xff0c;iPhone作为智能手机的佼佼者&#xff0c;早已融入了我们生活的方方面面。然而&#xff0c;当那熟悉的开机画面——“白苹果”意外地成为了你的日常&#xff0c;无疑让人头疼不已。别担心&#xff0c;今天我们就来聊聊iOS白苹果现象的成因及几种有效…

C#实现数据采集系统-多设备采集

系统功能升级-多设备采集 数据采集系统在网络环境下&#xff0c;性能足够&#xff0c;可以实现1对多采集&#xff0c;需要支持多个设备进行同时采集功能&#xff0c;现在就开发多设备采集功能 修改多设备配置 设备配置 将DeviceLink 改成List集合的DeviceLinks删掉Points&a…

运维开发——局域网SSH访问服务器与应用

摘要 本博文主要介绍局域网SSH访问登陆虚拟机和及其应用相关配置操作。 1. 局域网SSH访问登陆虚拟机 目标&#xff1a;在局域网内A电脑使用SSH登陆B电脑上虚拟机的服务器。 前提条件:B电脑为宿主机&#xff0c;可以正常使用ssh访问虚拟机服务器&#xff0c;虚拟机网络连接方…

数学强化| 李林880重点题速刷计划

快9月了&#xff0c;有的同学还没开始强化&#xff0c;进度确实有点慢了&#xff0c;有同学问&#xff1a; 刚开始强化&#xff0c;880题该如何快速刷完&#xff1f; 听我说&#xff0c;别急&#xff01;越是强化开始的晚&#xff0c;就越不能急&#xff0c;因为强化的作用有两…

【Datawhale AI 夏令营】第四期 基于2B源大模型 微调

定位&#xff1a;代码复现贴 教程&#xff1a;https://datawhaler.feishu.cn/wiki/PLCHwQ8pai12rEkPzDqcufWKnDd 模型加载 model AutoModelForCausalLM.from_pretrained(path, device_map"auto", torch_dtypetorch.bfloat16, trust_remote_codeTrue )AutoModelForC…

AI学习记录 - 如何快速构造一个简单的token词汇表

创作不易&#xff0c;有用的话点个赞 先直接贴代码&#xff0c;我们再慢慢分析&#xff0c;代码来自openai的图像分类模型的一小段 def bytes_to_unicode():"""Returns list of utf-8 byte and a corresponding list of unicode strings.The reversible bpe c…

压测工具哪个好?LoadRunner、Jmeter、Locust、Wrk 全方位对比....

当你想做性能测试的时候&#xff0c;你会选择什么样的测试工具呢&#xff1f;是会选择wrk&#xff1f;jmeter&#xff1f;locust&#xff1f;还是loadrunner呢&#xff1f;今天&#xff0c;笔者将根据自己使用经验&#xff0c;针对jmeter、locust、wrk和loadrunner常用的性能测…

前后端部署-服务器linux中部署Node.js环境

一.安装分布式版本管理系统Git (Alibaba Cloud Linux 3/2、CentOS 7.x) sudo yum install git -y 二.使用Git将NVM的源码克隆到本地的~/.nvm目录下&#xff0c;并检查最新版本。 git clone https://gitee.com/mirrors/nvm.git ~/.nvm && cd ~/.nvm && gi…

RVG29;狂犬病病毒肽;狂犬病病毒糖蛋白;115136-25-9;YTIWMPENPRPGTPCDIFTNSRGKRASNG

【RVG29 简介】 RVG29&#xff08;狂犬病病毒肽&#xff09;是一种由29个氨基酸组成的细胞穿透肽&#xff0c;它来源于狂犬病病毒糖蛋白。RVG肽能够特异性识别并结合中枢神经系统中普遍存在的烟碱型乙酰胆碱受体&#xff08;nAChR&#xff09;&#xff0c;并通过受体介导的转胞…

AR 眼镜之-系统应用音效-实现方案

目录 &#x1f4c2; 前言 AR 眼镜系统版本 系统应用音效 1. &#x1f531; 技术方案 1.1 技术方案概述 1.2 实现方案 1&#xff09;初始化 2&#xff09;播放音效 3&#xff09;释放资源 2. &#x1f4a0; 播放音效 2.1 静音不播放 2.2 获取音效默认音量 3. ⚛️ …

2.初识springcloud

文章目录 1.什么是SpringCloud1.1版本的介绍 2.Spring Cloud实现方案3.环境搭建4.服务拆分原则5.数据准备5.1订单服务5.2商品服务 大家好&#xff0c;我是晓星航。今天为大家带来的是 初识springcloud 相关的讲解&#xff01;&#x1f600; 1.什么是SpringCloud 简单来说&…

【算法基础实验】图论-最小生成树-Prim的即时实现

理论知识 Prim算法是一种用于计算加权无向图的最小生成树&#xff08;MST, Minimum Spanning Tree&#xff09;的贪心算法。最小生成树是一个连通的无向图的子图&#xff0c;它包含所有的顶点且总权重最小。Prim算法从一个起始顶点开始&#xff0c;不断将权重最小的边加入生成…

Excel表格添加趋势线_数据拟合

一个曲线通过补偿算法拟合为另一个曲线&#xff0c;通常可以通过多种数学和计算技术实现。这里也可以通过Excel表格添加趋势线&#xff0c;然后对趋势线进行拟合&#xff0c;得到趋势预测公式来达到数据补偿。 通过把你需要的数据导入到Excel表格中。 通过 “ 插入 ” --> “…

谷歌云AI新作:CROME,跨模态适配器高效多模态大语言模型

CROME: Cross-Modal Adapters for Efficient Multimodal LLM https://arxiv.org/pdf/2408.06610 Abstract 研究对象&#xff1a;Multimodal Large Language Models (MLLMs) demonstrate remarkable imagelanguage capabilities, but their widespread use faces challenges in…

论坛 推荐

畅议论坛&#xff1a;http://udbbs.top/http://udbbs.top/

查看U盘的具体信息,分区表格式、实际容量和分区状态

查看U盘的具体信息&#xff0c;分区表格式、实际容量和分区状态 前言&#xff1a; 利用windows自带的命令行窗口就可以 1、使用命令提示符查看MBR和GPT分区类型 &#xff08;1&#xff09;按“Windows R”键&#xff0c;在弹出的运行对话框中输入“diskpart”&#xff0c;并按…

游戏开发设计模式之工厂模式

目录 简单工厂模式&#xff08;Simple Factory Pattern&#xff09; 应用场景&#xff1a; 优缺点&#xff1a; 工厂方法模式&#xff08;Factory Method Pattern&#xff09; 应用场景&#xff1a; 优缺点&#xff1a; 抽象工厂模式&#xff08;Abstract Factory Patte…