当前位置: 首页 > article >正文

【算法】BFS 系列之 多源 BFS

【ps】本篇有 4 道 leetcode OJ。 

目录

一、算法简介

二、相关例题

1)01 矩阵

.1- 题目解析

.2- 代码编写

2)飞地的数量

.1- 题目解析

.2- 代码编写

3)地图中的最高点

.1- 题目解析

.2- 代码编写

4)地图分析

.1- 题目解析

.2- 代码编写


一、算法简介

        最短路问题是图论中一种经典的题型,包括单源最短路、多源最短路、边权为 1 的最短路等等。本篇主要讲述的是边权为 1 的多源最短路问题。

        简单来说,边权为 1 的单源最短路问题即为:求从单个起点到终点的最短路径距离,而边权为 1 的多源最短路问题即为:求从多个起点到终点的最短路径距离。

        对于多源的最短路问题,我们将多个相邻的起点看作是一个整体,进而简化成一个起点,将多源转化成单源并利用 BFS 来处理,具体的方式是,在用队列进行 BFS 时,将所有起点入队,然后一层一层向外扩展。

 ​

二、相关例题

1)01 矩阵

542. 01 矩阵

.1- 题目解析

        我们可以选择正难则反,不将 1 作为起点,而将 0 作为起点进行多源 BFS,去看 0 到达每个 1 的距离,从而得出最终的结果矩阵。

        可以先把所有的 0 都放在队列中,把它们当成一个整体,每次把当前队列里面的所有元素向外扩展一次。在遍历的时候还需要标记一下处理过的 1 ,这样才能做到只遍历整个矩阵一次,具体的方式是,在创建结果矩阵之初,将矩阵元素的值全都初始化为 -1。

.2- 代码编写

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();
        vector<vector<int>> dist(m,vector<int>(n,-1));
        //dist[i][j]==-1,表示没有被搜索过
        //dist[i][j]!=-1,表示最短距离
        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;
                }
            }
        }
        //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<m && y>=0 && y<n && dist[x][y]==-1)
                {
                    dist[x][y]=dist[a][b]+1;//每向外扩展一次,就相当于向外走了一步
                    q.push({x,y});
                }
            }
        }
        return dist;
    }
};

2)飞地的数量

1020. 飞地的数量

.1- 题目解析

        与上道题类似,我们也可以正难则反,从矩阵边上的 1 开始搜索,把与这些 1 相连的区域全部标记一下,然后再遍历一遍矩阵,统计哪些位置的 1 没有被标记即可,这些没有被标记的 1 就是不能到达边界的陆地。

.2- 代码编写

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 全部入队
        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;
                    }
                }
            }
        }
        //进行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<m && y>=0 && y<n 
                && grid[x][y]==1 && !vis[x][y])
                {
                    vis[x][y]=true;
                    q.push({x,y});
                }
            }
        }
        //统计结果
        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)地图中的最高点

1765. 地图中的最高点

.1- 题目解析

        本题类似于上文的《01矩阵》,也可以选择正难则反,以水域为起点,通过 BFS 向外扩展来安排结果矩阵中每个元素的高度,使得结果矩阵中的高度(元素)之和最大。

.2- 代码编写

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;
        for(int i=0;i<m;i++)
            for(int j=0;j<n;j++)
                if(isWater[i][j])
                {
                    dist[i][j]=0;
                    q.push({i,j});
                }
        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});
                }
            }
        }
        return dist;
    }
};

4)地图分析

1162. 地图分析

.1- 题目解析

        本题类似于上文的《01矩阵》,曼哈顿距离其实就是最短距离,于是也可以选择正难则反,以陆地为起点,通过 BFS 向海洋去扩展。

 

.2- 代码编写

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])
                {
                    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.kler.cn/news/312779.html

相关文章:

  • Unity之FPS
  • 谷粒商城のElasticsearch
  • 优先级队列(堆)
  • 行业分析---自动驾驶行业的发展
  • MySQL定长窗口SQL
  • Spring为什么要用三级缓存解决循环依赖?
  • 微服务之服务注册与发现:Etcd、Zookeeper、Consul 与 Nacos 比较
  • libmodbus:写一个modbusTCP服务
  • 求Huffman树及其matlab程序详解
  • RabbitMQ 常见使用模式详解
  • Delta Lake
  • jetcache-阿里多级缓存框架神器一定要掌握
  • 【Kubernetes知识点】HPA如何控制不同的资源实现自动扩缩容?
  • 青柠视频云——如何开启HTTPS服务?
  • 最新植物大战僵尸杂交版V2.5版本【包含历史版本!持续更新!!】
  • 告别繁琐粘贴,CleanClip Mac 版,让复制粘贴变得简单快捷!粘贴队列功能太强大了!
  • Windows上,使用远程桌面连接Ubuntu
  • Java知识点小结3:内存回收
  • 2024.09.12校招 实习 内推 面经
  • Redis---关闭Redis服务端
  • 操作数组不越界的妙法C++
  • 光伏发电量估算有多重要?如何分析?
  • Java22-匿名变量/模式(Unnamed Variables Patterns)
  • k8s自动清理pod脚本分享
  • Web网站常用测试工具
  • Java【代码 18】处理Word文档里的Excel表格数据(源码分享)
  • 【系统架构设计师-2013年真题】案例分析-答案及详解
  • Leetcode 和为 K 的子数组
  • 【深度学习 Transformer VIT】Transformer VIT:拆解“视觉变形金刚”,笑谈技术细节
  • 【Android源码】屏蔽系统通知出现在系统栏中