[Algorithm][多源BFS][矩阵][飞地的数量][地图中的最高点][地图分析] + 多源BFS原理讲解 详细讲解

目录

  • 0.原理讲解
  • 1.矩阵
    • 1.题目链接
    • 2.算法原理详解
    • 3.代码实现
  • 2.飞地的数量
    • 1.题目链接
    • 2.算法原理详解
    • 3.代码实现
  • 3.地图中的最高点
    • 1.题目链接
    • 2.算法原理详解
    • 3.代码实现
  • 4.地图分析
    • 1.题目链接
    • 2.算法原理详解
    • 3.代码实现


0.原理讲解

  • 注意:只要是用**BFS解决的最短路径问题,都要求边权为一(边权值相同)**

  • 单源最短路径

    • 把起点加入到队列中
    • 一层一层的往外扩展
  • 多源BFS:用BFS解决边权为一多源最短路径问题
    请添加图片描述

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

    • 效率低,大概率会超时
  • 法二:把所有的源点当成一个"超级源点"

    • 此时问题就变成了「单源最短路径」问题
      请添加图片描述
  • "超级源点"的正确性?感性理解

    • 同时从几个源点出发,会存在"舍弃"几个"不好的点"的现象
    • 远的源点走一步肯定没有近的源点走一步好,所以相当于舍去了远的源点
  • 多源BFS如何代码实现?

    • 所有的源点加入到队列里面
    • 一层一层的往外扩展
      请添加图片描述

1.矩阵

1.题目链接

  • 矩阵

2.算法原理详解

  • 思路一:一个位置一个位置求

    • 不用想,这么暴力肯定超时:P
  • 思路二多源BFS + 正难则反 -> 把所有的0当成起点,1当成终点

    • 把所有的0位置加入到队列中
    • 一层一层的向外拓展即可
      请添加图片描述
  • 为什么正着做会很困难呢?

    • 正着做虽然能找到0,但是想把距离存下来,会很难
    • 并且也无法知道是哪个1到了0,距离是多少
  • 为什么本题用到了多源BFS呢?

    • 0是有很多个的,怎么才能保证遇到的1距离这⼀个0是最近的?
    • 先把所有的0都放在队列中,把它们当成⼀个整体,每次把当前队列⾥⾯的所有元素向外扩展⼀次
  • 细节:在单源最短路径中需要:bool visit[i][j]stepsz,而在多源BFS中,只需要一个int dist[i][j]就可以替代这三者的功能

    • 为什么可以替代bool visit[i][j]
      • dist[][]初始化为-1-1表示没有搜索过
      • dist[i][j] != -1则为最短距离
    • <为什么可以替代step
      • (a, b) -> (x, y)dist[a][b]存储了dist[x][y]上一步的距离
        • dist[x][y] = dist[a][b] + 1
    • 为什么可以替代sz
      • 因为不强制一定要按层一层一层出队列,可以一个元素一个元素的往外扩展
      • 不需要知道此时是哪一层,dist[i][j]已经标记了现在是属于哪一层

3.代码实现

vector<vector<int>> UpdateMatrix(vector<vector<int>>& mat) 
{
    int n = mat.size(), m = mat[0].size();

    // dist[i][j] == -1 未搜索过
    // dist[i][j] != -1 最短距离
    vector<vector<int>> dist(n, vector<int>(m, -1));
    queue<pair<int, int>> q;

    // 将所有源点加入到队列中
    for(int i = 0; i < n; i++)
    {
        for(int j = 0; j < m; j++)
        {
            if(mat[i][j] == 0)
            {
                q.push({i, j});
                dist[i][j] = 0;
            }
        }
    }

    // 多源BFS
    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 < n && y >= 0 && y < m && dist[x][y] == -1)
            {
                dist[x][y] = dist[a][b] + 1;
                q.push({x, y});
            }
        }
    }

    return dist;
}

2.飞地的数量

1.题目链接

  • 飞地的数量

2.算法原理详解

  • 思路一:一个一个去判断
    • 不用想,这么暴力肯定超时:P
  • 思路二多源BFS + 正难则反 -> 从边界上的1开始,做一次搜索
    • 多源BFS结束后,重新遍历一次数组,最后剩下来的就都是飞地
      请添加图片描述

3.代码实现

int NumEnclaves(vector<vector<int>>& grid) 
{
    int n = grid.size(), m = grid[0].size();
    vector<vector<bool>> visit(n, vector<bool>(m, false));
    queue<pair<int, int>> q;

    // 将所有边界1入队列
    for(int i = 0; i < n; i++)
    {
        if(grid[i][0] == 1)
        {
            q.push({i, 0});
            visit[i][0] = true;
        }

        if(grid[i][m - 1] == 1)
        {
            q.push({i, m - 1});
            visit[i][m - 1] = true;
        }
    }

    for(int i = 0; i < m; i++)
    {
        if(grid[0][i] == 1)
        {
            q.push({0, i});
            visit[0][i] = true;
        }

        if(grid[n - 1][i] == 1)
        {
            q.push({n - 1, i});
            visit[n - 1][i] = true;
        }
    }

    // 多源BFS
    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 < n && y >= 0 && y < m \
               && grid[x][y] == 1 && !visit[x][y])
            {
                visit[x][y] = true;
                q.push({x, y});
            }
        }
    }

    // 遍历计数
    int count = 0;
    for(int i = 0; i < n; i++)
    {
        for(int j = 0; j < m; j++)
        {
            if(grid[i][j] == 1 && !visit[i][j])
            {
                count++;
            }
        }
    }

    return count;
}

3.地图中的最高点

1.题目链接

  • 地图中的最高点

2.算法原理详解

  • "01矩阵"变形题,直接多源BFS即可

3.代码实现

class Solution 
{
    int dx[4] = {1, -1, 0, 0};
    int dy[4] = {0, 0, 1, -1};
public:
    vector<vector<int>> highestPeak(vector<vector<int>>& isWater) 
    {
        int n = isWater.size(), m = isWater[0].size();
        vector<vector<int>> dist(n, vector<int>(m, -1));
        queue<pair<int, int>> q;
        
        // 将边界水域入队列
        for(int i = 0; i < n; i++)
        {
            for(int j = 0; j < m; j++)
            {
                if(isWater[i][j])
                {
                    dist[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], y = b + dy[i];

                if(x >= 0 && x < n && y >= 0 && y < m && dist[x][y] == -1)
                {
                    dist[x][y] = dist[a][b] + 1;
                    q.push({x, y});
                }
            }
        }

        return dist;
    }
};

4.地图分析

1.题目链接

  • 地图分析

2.算法原理详解

  • "01矩阵"变形题,直接多源BFS即可

3.代码实现

class Solution 
{
    int dx[4] = {1, -1, 0, 0};
    int dy[4] = {0, 0, 1, -1};
public:
    int maxDistance(vector<vector<int>>& grid) 
    {
        int n = grid.size();
        vector<vector<int>> dist(n, vector(n, -1));
        queue<pair<int, int>> q;

        // 将陆地入队列
        for(int i = 0; i < n; i++)
        {
            for(int j = 0; j < n; j++)
            {
                if(grid[i][j])
                {
                    dist[i][j] = 0;
                    q.push({i, j});
                }
            }
        }

        // 多源BFS
        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 < n && 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;
    }
};

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

韩顺平0基础学Java——第5天

p72——p86 今天同学跟我说别学java&#xff0c;真的吗&#xff1f;唉&#xff0c;先把这视频干完吧。 逻辑运算符练习 x6&#xff0c;y6 x6&#xff0c;y5 x11&#xff0c;y6 x11&#xff0c;y5 z48 错了&a…

【web网页制作】html+css旅游家乡河南开封主题网页制作(4页面)【附源码】

HTMLCSS家乡河南主题网页目录 &#x1f354;涉及知识&#x1f964;写在前面&#x1f367;一、网页主题&#x1f333;二、页面效果Page1 首页Page2 开封游玩Page 3 开封美食Page4 留言 &#x1f308; 三、网页架构与技术3.1 脑海构思3.2 整体布局3.3 技术说明书 &#x1f40b;四…

【Git】Git学习-14:VSCode中使用git

学习视频链接&#xff1a;【GeekHour】一小时Git教程_哔哩哔哩_bilibili​编辑https://www.bilibili.com/video/BV1HM411377j/?vd_source95dda35ac10d1ae6785cc7006f365780 在vscode中打开文件 code . 自行修改内容&#xff0c;在源代码管理器中测试下

flutter报错

组件相关 type ‘List’ is not a subtype of type ‘List’ children: CardList.map((item) > Container( 加上 *** < Widget>*** 正常 type ‘(dynamic, dynamic) > Container’ is not a subtype of type ‘(CardType) > Widget’ of ‘f’ children: CardL…

Spring Data JPA自定义Id生成策略、复合主键配置、Auditing使用

前言 在Spring Data JPA系列的第一篇文章 SpringBoot集成JPA及基本使用-CSDN博客 中讲解了实体类的Id生成策略可以通过GeneratedValue注解进行配置&#xff0c;该注解的strategy为GenerationType类型&#xff0c;GenerationType为枚举类&#xff0c;支持四种Id的生成策略&…

详细讲解lua中string.gsub的使用

string.gsub 是 Lua 标准库中的一个函数&#xff0c;用于全局替换字符串中的某些部分。string.gsub 是 Lua 中非常实用的一个函数&#xff0c;它可以用来进行字符串的处理和替换操作。 它的基本语法如下&#xff1a; string.gsub(s, pattern, replacement [, n])s 是要处理的…

鸿蒙开发核心技术都有哪些【都是从零开始】

鸿蒙开发核心技术都有哪些&#xff1f;&#xff1a;【持续1年的时间公关鸿蒙技术】 我们能做哪些呢&#xff1f; 还是从UI业务开始吧 面试题1&#xff1a; 基于STAGE模型项目重构等问题 代理设计模式&#xff0c;业务与架构隔离 中介者模式&#xff0c;和代理设计模式的区别…

项目管理-项目绩效域1/2

项目管理&#xff1a;每天进步一点点~ 活到老&#xff0c;学到老 ヾ(◍∇◍)&#xff89;&#xff9e; 何时学习都不晚&#xff0c;加油 1.项目绩效域--整体框架 项目绩效域 重点&#xff1a; ①八大绩效域的含义。 ②八大绩效域的问题和解决方案。 ③八大绩效域与十大管…

Go标准库——Flag库和Log库

一.Flag Go语言内置的flag包实现了命令行参数的解析&#xff0c;flag包使得开发命令行工具更为简单。 1.1 os.Args 如果你只是简单的的想要获取命令行参数&#xff0c;可以像下面代码示例一样使用os.Args来获取命令行参数。 os.Arg实际是一个存储命令行参数的字符串切片([]stri…

Linux最新提权通杀五大绝招(上)

点击星标&#xff0c;即时接收最新推文 本文选自《内网安全攻防&#xff1a;红队之路》 扫描二维码五折购书 Linux 主机权限提升问题是普遍存在的。在Web 服务器、数据库、防火墙、IOT等基础设施中&#xff0c;大部分都运行着Linux 操作系统&#xff0c;鉴于Linux 设备在大量基…

【负载均衡在线OJ项目日记】项目简介

目录 前言 什么是负载均衡 所用的技术和开发环境 所用技术 开发环境 项目的宏观结构 leetcode 结构 结构 编写思路 前言 从C语言的文章到现在Linux网络部分&#xff0c;我已经涉猎了很多知识&#xff1b;终于在今天我要开始搞项目了&#xff0c;通过项目我也可以开始…

鸿蒙OS NEXT的推出,不仅面向App端

华为官方公布6月份的版本为beta版&#xff0c;依然属于开发者测试版&#xff0c;但可以向普通用户开放了。这点和苹果iOS系统测试形式略微相似&#xff1a;6月份开放首个测试版&#xff0c;随后过渡到公测版&#xff0c;最后再和年度新机一起发布正式版系统。 如果按照这个进度…

DNS域名解析服务的部署及优化方案

实验要求: 1.配置2台服务器要求如下&#xff1a; a&#xff09;服务器1&#xff1a; 主机名&#xff1a;dns-master.timinglee.org ip地址&#xff1a; 172.25.254.100 配置好软件仓库 b&#xff09;服务器2&#xff1a; 主机名&#xff1a;dns-slave.timinglee.org ip地址&am…

fero - yolo - mamba:基于选择性状态空间的面部表情检测与分类

fero - yolo - mamba:基于选择性状态空间的面部表情检测与分类 摘要IntroductionRelated work FER-YOLO-Mamba: Facial Expression Detection and Classification Based on Selective State Space 摘要 面部表情识别&#xff08;FER&#xff09;在理解人类情绪线索方面起着关键…

S型曲线的几种设计(图像对比度调节)

一般来讲&#xff0c;图像调色模块都会提供“曲线”工具&#xff0c;这是一个极其灵活的功能&#xff0c;绝大部分的调色都可以通过该工具实现&#xff0c;但是曲线功能的交互相对而言比较复杂。出于简便性和效率方面的考量&#xff0c;调色模块往往还会提供一些具有很强的功能…

Angular中创建和使用服务

Angular中的服务 文章目录 Angular中的服务前言一、创建服务二、使用服务 前言 Angular 服务是 Angular 应用程序中用于封装可重用逻辑的类。服务在应用程序的多个组件之间共享数据和功能&#xff0c;而不依赖于应用程序的UI。服务可以用于诸如数据处理、与后端通信、用户身份…

电脑显示丢失mfc140u.dll怎么修复,总共有7个方法

mfc140u.dll 是一个动态链接库&#xff08;Dynamic Link Library&#xff09;文件&#xff0c;它是Microsoft Foundation Class (MFC)库的一部分&#xff0c;专为使用C编程语言开发Windows应用程序而设计。MFC库由微软提供&#xff0c;作为一个高级的应用程序框架&#xff0c;旨…

通过 Java 操作 redis -- 连接 redis

如果我们想在本地主机上访问 Linux 服务器上的 redis &#xff0c;我们就需要通过 ssh 进行端口转发&#xff0c;推荐看 本地主机访问服务器的Redis -- 配置 ssh 端口转发 通过 Java 操作 redis 已经有大佬创建了很多第三方库&#xff0c;这里我们使用 jedis &#xff0c;因为它…

N7552A是德科技N7552A电子校准件

181/2461/8938产品概述&#xff1a; 更小巧轻便的 2 端口模块&#xff0c;支持 3.5 mm 或 N 型 50 Ω 连接器&#xff0c;能够将校准时间缩短一半 特点 频率范围&#xff1a;直流至 9 GHz 使用 N 型或 3.5 mm 连接器 更小巧轻便的 2 端口电子校准件&#xff08;ECal&#xff…

Linux:进程等待 进程替换

Linux&#xff1a;进程等待 & 进程替换 进程等待wait接口statuswaitpid接口 进程替换exec系列接口 当一个进程死亡后&#xff0c;会变成僵尸进程&#xff0c;此时进程的PCB被保留&#xff0c;等待父进程将该PCB回收。那么父进程要如何回收这个僵尸进程的PCB呢&#xff1f;父…