算法笔记(十四)——多源 BFS

文章目录

多源 BFS

单源最短路问题:一个起点到一个终点的最短路;
解决步骤:

  • 把起点放进队列里
  • 一层一层往外扩

相关文章: 算法笔记(十三)------BFS 解决最短路问题
多源最短路问题:多个起点到同一个终点的最短路;
多源BFSBFS来解决多源最短路问题
如何解决???

  • 把所有源点当成一个源点 <==> 单一的最短路问题

解决步骤

  • 把所有起点放进队列里
  • 一层一层往外扩

01 矩阵

题目:01 矩阵


思路

1当作起点,0当作终点的话,我们逆推起点比较麻烦,所以我们反着想;将0当作起点,1当作终点,这样就可以直接将答案填在答案数组的终点位置中;

  • 遍历原数组将所有0放入队列
  • 一层一层向外拓展

C++代码

cpp 复制代码
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>> ret(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(mat[i][j] == 0)
                {
                    q.push({i, j});
                    ret[i][j] = 0;
                }

        while(!q.empty())
        {
            auto [a, b] = q.front();
            q.pop();
            for(int i = 0; i < 4; i++)
            {
                int x = a + dx[i], y = b + dy[i]; 
                if(0 <= x && x < m && 0 <= y && y < n && ret[x][y] == -1)
                {
                    ret[x][y] = ret[a][b] + 1;
                    q.push({x, y});
                }
            }
        }

        return ret;
    }
};

飞地的数量/font>

题目:飞地的数量


思路

逆向思维
(单源BFS) 从边缘开始以1为起点开始单源BFS当遇到1时,将其更改为0

(单源BFS) 从边缘的1进行遍历

最后遍历原数组grid,其中1的个数为答案,即无法出去的数量

C++代码(单源BFS)

cpp 复制代码
class Solution 
{
    const int dx[4]={0,0,1,-1};
    const int dy[4]={-1,1,0,0};
    int m, n;
    queue<pair<int, int>> q;
    void bfs(vector<vector<int>>& grid, int i, int j)
    {
        q.push({i, j});
        grid[i][j] = 0;

        while(!q.empty())
        {
            int sz = q.size();
            for(int i = 0; i < sz; i++)
            {
                auto [a, b] = q.front();
                q.pop();
                for(int k = 0; k < 4; k++)
                {
                    int x = a + dx[k], y = b + dy[k];
                    if(0 <= x && x < m && 0 <= y && y < n && grid[x][y] == 1)
                    {
                        grid[x][y] = 0;
                        q.push({x, y});
                    }
                }
            }
        }
    }
public:
    int numEnclaves(vector<vector<int>>& grid) 
    {
        m = grid.size(), n = grid[0].size();
        for(int i = 0; i < m; i++)
        {
            if(grid[i][0] == 1) bfs(grid, i, 0);
            if(grid[i][n - 1] == 1) bfs(grid, i, n - 1);
        }
        for(int i = 1; i < n - 1; i++)
        {
            if(grid[0][i] == 1) bfs(grid, 0, i);
            if(grid[m - 1][i] == 1) bfs(grid, m - 1, i);
        }

        int ret = 0;
        for(int i = 0; i < m; i++)
            for(int j = 0; j < n; j++)
                if(grid[i][j] == 1) ret += 1;
        
        return ret;
    }
};

C++代码(多源BFS)

cpp 复制代码
class Solution 
{
    // 定义四个方向的坐标变化
    const int dx[4] = {0, 0, 1, -1};
    const 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>> visited(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});
                        visited[i][j] = true;
                    }

        // 2. 多源 BFS
        while (!q.empty()) 
        {
            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 && !visited[x][y]) 
                {
                    visited[x][y] = true;
                    q.push({x, y});
                }
            }
        }

        // 3. 统计结果
        int ret = 0;
        for (int i = 0; i < m; i++)
            for (int j = 0; j < n; j++)
                // 统计未被包围的陆地单元格数量
                if (grid[i][j] == 1 && !visited[i][j])
                    ret++;
        return ret;
    }
};

地图中的最高点

题目:地图中的最高点


思路

  • 读完题后,本题思路和01矩阵基本一样;
  • 要想使最高高度值最大,我们从0位置向外拓展一层,将为访问的区域+1,循环,直至矩阵中全部都被遍历;

C++代码

cpp 复制代码
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] == 1)
                {
                    q.push({i, j});
                    dist[i][j] = 0;
                }

        while(!q.empty())
        {
            auto [a, b] = q.front(); q.pop();
            for(int i = 0; i < 4; i++)
            {
                int x = a + dx[i], y = b + dy[i];
                if(0 <= x && x < m && 0 <= y && y < n && dist[x][y] == -1)
                {
                    dist[x][y] = dist[a][b] + 1;
                    q.push({x, y});
                }
            }
        }

        return dist;
    }
};

地图分析

题目:地图分析


思路

海洋到陆地的最大<==>陆地到海洋的最大

和上面代码基本一样,只需修改最终结果

C++代码

cpp 复制代码
class Solution 
{
    int dx[4] = {1, -1, 0, 0};
    int dy[4] = {0, 0, 1, -1};
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])
                {
                    q.push({i, j});
                    dist[i][j] = 0;
                }

        int ret = -1;
        while(!q.empty())
        {
            auto [a, b] = q.front(); q.pop();
            for(int i = 0; i < 4; i++)
            {
                int x = a + dx[i], y = b + dy[i];
                if(0 <= x && x < m && 0 <= y && 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;
    }
};
相关推荐
寒秋花开曾相惜20 小时前
(学习笔记)第四章 处理器体系结构
linux·网络·数据结构·笔记·学习
故事和你9120 小时前
洛谷-数据结构1-1-线性表1
开发语言·数据结构·c++·算法·leetcode·动态规划·图论
脱氧核糖核酸__21 小时前
LeetCode热题100——53.最大子数组和(题解+答案+要点)
数据结构·c++·算法·leetcode
脱氧核糖核酸__21 小时前
LeetCode 热题100——42.接雨水(题目+题解+答案)
数据结构·c++·算法·leetcode
王老师青少年编程1 天前
csp信奥赛C++高频考点专项训练之贪心算法 --【线性扫描贪心】:数列分段 Section I
c++·算法·编程·贪心·csp·信奥赛·线性扫描贪心
王老师青少年编程1 天前
csp信奥赛C++高频考点专项训练之贪心算法 --【线性扫描贪心】:分糖果
c++·算法·贪心算法·csp·信奥赛·线性扫描贪心·分糖果
_日拱一卒1 天前
LeetCode:2两数相加
算法·leetcode·职场和发展
py有趣1 天前
力扣热门100题之零钱兑换
算法·leetcode
董董灿是个攻城狮1 天前
Opus 4.7 来了,我并不建议你升级
算法
LN花开富贵1 天前
【ROS】鱼香ROS2学习笔记二
linux·笔记·python·学习·嵌入式