lc542. 01 矩阵 (广度优先搜索、动态规划)

题目:
542. 01 矩阵

 

题解:

一、广度优先搜索

如果从每个1出发,广度优先搜索它临近的0,每一次搜索,只能更新当前1的信息,会比较耗时。因此,我们可以从矩阵中的所有0出发,寻找到每个1的距离,这个方法也称多源广度优先搜索

例如:1、从所有的0出发搜索,找到了5个1(浅黄绿色)(距离为1),再从这5个1出发,到达中间1的位置(距离为2)。

 

 

第一步从超级源点出发,第二步就能到达矩阵中所有的0,第三步就能到达第一层1(5个)...

具体步骤:

1、初始化输出的距离矩阵dist,所有0位置的距离为0,所有1的距离设为INT_MAX,后面根据广度优先搜索更新结果

2、初始化队列q来存储BFS需要搜索的位置,先将所有0的位置加入q

3、抛出队列中的元素{a,b},搜索它的邻居,如果邻居{i,j}新计算的距离更小dist[a][b] + 1 < dist[i][j],将{i,j}加入队列q中,同时更新d[i][j] = dist[a][b] + 1

 

class Solution {
public:
    vector<vector<int>> updateMatrix(vector<vector<int>>& mat) {
        int m = mat.size();
        int n = mat[0].size();
// 1、初始化输出的距离矩阵dist,所有0位置的距离为0,所有1的距离设为INT_MAX,后面根据广度优先搜索更新结果
        vector<vector<int>> dist(m, vector<int>(n, INT_MAX));
// 2、初始化队列q来存储BFS需要搜索的位置,先将所有0的位置加入q
        queue<pair <int, int>> q;
        for (int i = 0; i < m; ++i) {
            for (int j = 0; j < n; ++j) {
                if (mat[i][j] == 0){
                    dist[i][j] = 0;
                    q.push({i, j});
                }
            }
        }
// 3、抛出队列中的元素{a,b},搜索它的邻居,如果邻居{i,j}新计算的距离更小dist[a][b] + 1 < dist[i][j],
// 则将{i,j}加入队列q中,同时更新d[i][j] = dist[a][b] + 1
        int dir[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};  // 上下左右
        while (!q.empty()) {
            int a = q.front().first;
            int b = q.front().second;
            q.pop();
            for  (int i = 0; i < 4; ++i) {
                int newR = a + dir[i][0];
                int newC = b + dir[i][1];
                if (newR >=0 && newR < m && newC >=0 && newC < n) {
                    if (dist[a][b] + 1 < dist[newR][newC]) {
                        q.push({newR, newC});
                        dist[newR][newC] = dist[a][b] + 1;
                    }
                }
            }
        }
        return dist;
    }
};

  

 

 

 

 

 

二、动态规划

 

因此我们分别从四个角开始递推,比如从左上角出发(只有 水平向左移动 和 竖直向上移动)

 

 

 

对于另外三种移动方法,我们也可以写出类似的状态转移方程,得到四个 f(i, j)的值,那么其中最小的值就表示位置 (i, j)到最近的 0 的距离。

class Solution {
public:
    vector<vector<int>> updateMatrix(vector<vector<int>>& mat) {
        int m = mat.size();
        int n = mat[0].size();
        // 初始化动态规划的数组,所有的距离值都设置为一个很大的数
        vector<vector<int>> dp(m, vector<int>(n, INT_MAX - 1000));
        // 如果 (i, j) 的元素为 0,那么距离为 0
        for (int i = 0; i < m; ++i) {
            for (int j = 0; j < n; ++j) {
                if(mat[i][j] == 0) {
                    dp[i][j] = 0;
                }
            }
        }

        // 注意 < 还是 <=  !!
        // 只有 水平向左移动 和 竖直向上移动,注意动态规划的计算顺序
        // 从左上角开始递推
        for (int i = 0; i < m; ++i) {
            for (int j = 0; j < n; ++j) {
                if (i - 1 >= 0) {
                    dp[i][j] = min(dp[i][j], dp[i-1][j] + 1);   // to up
                }
                if (j - 1 >= 0) {
                    dp[i][j] = min(dp[i][j], dp[i][j-1] + 1);  //to left
                }
            }
        }
        // 只有 水平向左移动 和 竖直向下移动,注意动态规划的计算顺序
        // 右上角
        for (int i = m - 1; i > 0; --i) {
             for (int j = 0; j < n; ++j) {
                if (i + 1 < m) {
                    dp[i][j] = min(dp[i][j], dp[i+1][j] + 1); 
                }
                if (j - 1 >= 0) {
                    dp[i][j] = min(dp[i][j], dp[i][j-1] + 1); 
                }
            }
        }
        // 只有 水平向右移动 和 竖直向上移动,注意动态规划的计算顺序
        // 左下角
        for (int i = 0; i < m; ++i) {
            for (int j = n - 1; j >= 0; --j) {
                if (i - 1 >= 0) {
                    dp[i][j] = min(dp[i][j], dp[i - 1][j] + 1);
                }
                if (j + 1 < n) {
                    dp[i][j] = min(dp[i][j], dp[i][j + 1] + 1);
                }
            }
        }
        // 只有 水平向右移动 和 竖直向下移动,注意动态规划的计算顺序
        // 右下角
        for (int i = m - 1; i >= 0; --i) {
            for (int j = n - 1; j >= 0; --j) {
                if (i + 1 < m) {
                    dp[i][j] = min(dp[i][j], dp[i + 1][j] + 1);
                }
                if (j + 1 < n) {
                    dp[i][j] = min(dp[i][j], dp[i][j + 1] + 1);
                }
            }
        }
        return dp;
    }
};

  

 

参考:

https://leetcode.cn/problems/01-matrix/solution/01ju-zhen-by-leetcode-solution/

https://leetcode.cn/problems/01-matrix/solution/2chong-bfs-xiang-jie-dp-bi-xu-miao-dong-by-sweetie/

posted @ 2023-01-14 17:48  blogzzt  阅读(23)  评论(0编辑  收藏  举报