zoukankan      html  css  js  c++  java
  • leetcode 542 01矩阵(多源BFS or dp)

    题目描述:

      给定一个由0和1组成的矩阵,找出每个元素到最近0的距离,两个相邻元素间的距离为1.

    题解:

      BFS:

      先考虑只有一个零的情况,那么只需要从这个零出发BFS更新距离就好。现在矩阵中有多个零,那么我们将这个多个零看作同一层(也可以理解为一个零的集合),然后以这个集合为起点同步BFS即可。举个例子,在这个例子中,有两个 0:  

    _ _ _ _
    _ 0 _ _
    _ _ 0 _
    _ _ _ _

    我们会把这两个 0 的位置都加入初始队列中,随后我们进行广度优先搜索,找到所有距离为 1 的 1:

    _ 1 _ _
    1 0 1 _
    _ 1 0 1
    _ _ 1 _

    接着重复步骤,直到搜索完成:

    _ 1 _ _         2 1 2 _         2 1 2 3
    1 0 1 _   ==>   1 0 1 2   ==>   1 0 1 2
    _ 1 0 1         2 1 0 1         2 1 0 1
    _ _ 1 _         _ 2 1 2         3 2 1 2

    理解清楚BFS的层次遍历方式之后,上述多源BFS理解起来应该不难。代码如下:

    class Solution {
    public:
        // bfs  dp
        int dir[4][2] = {{1,0},{-1,0},{0,1},{0,-1}};
        typedef pair<int,int> pii;
        vector<vector<int>> updateMatrix(vector<vector<int>>& matrix) {
            int n = matrix.size(), m = matrix[0].size();
            vector<vector<int>> ans(n,vector<int>(m,INT_MAX/2));
            int vis[n+1][m+1];
            memset(vis,0,sizeof(vis));
            queue<pii> que;
            for(int i=0;i<n;i++)
            {
                for(int j=0;j<m;j++)
                {
                    if(matrix[i][j] == 0)
                    {
                        vis[i][j] = 1;
                        ans[i][j] = 0;
                        que.emplace(i,j);
                    }
                }
            }
    
            while(!que.empty())
            {
                pii now = que.front();
                que.pop();
                for(int i=0;i<4;i++)
                {
                    int xx = now.first + dir[i][0];
                    int yy = now.second + dir[i][1];
                    if(xx < 0 || xx>=n || yy < 0 || yy >=m || vis[xx][yy] == 1) continue;
                    ans[xx][yy] = min(ans[xx][yy],ans[now.first][now.second] + 1);
                    vis[xx][yy] = 1;
                    que.emplace(xx,yy);
                }
            }
            return ans;
        }
    };

      DP:

      定义dp[i][j]为位置i,j到最近0的距离。需要梳理清楚的是dp的递推过程,也就是建立一个有序的状态转移。这里$f[x][y]$可以由$f[x][y-1]、f[x][y+1]、f[x-1][y]、f[x+1][y]$四个状态转移而来,那么至少需要遍历两次矩阵,分别为:

    • 只有 水平向左移动 和 竖直向上移动;

    • 只有 水平向右移动 和 竖直向下移动。

      限制好移动的方向之后,状态的转移就比较简单了,详见代码:

      

    class Solution {
    public:
        vector<vector<int>> updateMatrix(vector<vector<int>>& matrix) {
            int m = matrix.size(), n = matrix[0].size();
            // 初始化动态规划的数组,所有的距离值都设置为一个很大的数
            vector<vector<int>> dist(m, vector<int>(n, INT_MAX / 2));
            // 如果 (i, j) 的元素为 0,那么距离为 0
            for (int i = 0; i < m; ++i) {
                for (int j = 0; j < n; ++j) {
                    if (matrix[i][j] == 0) {
                        dist[i][j] = 0;
                    }
                }
            }
            // 只有 水平向左移动 和 竖直向上移动,注意动态规划的计算顺序
            for (int i = 0; i < m; ++i) {
                for (int j = 0; j < n; ++j) {
                    if (i - 1 >= 0) {
                        dist[i][j] = min(dist[i][j], dist[i - 1][j] + 1);
                    }
                    if (j - 1 >= 0) {
                        dist[i][j] = min(dist[i][j], dist[i][j - 1] + 1);
                    }
                }
            }
            // 只有 水平向右移动 和 竖直向下移动,注意动态规划的计算顺序
            for (int i = m - 1; i >= 0; --i) {
                for (int j = n - 1; j >= 0; --j) {
                    if (i + 1 < m) {
                        dist[i][j] = min(dist[i][j], dist[i + 1][j] + 1);
                    }
                    if (j + 1 < n) {
                        dist[i][j] = min(dist[i][j], dist[i][j + 1] + 1);
                    }
                }
            }
            return dist;
        }
    };
  • 相关阅读:
    discuz论坛X3升级时 文件下载出现问题,请查看您的服务器网络以及data目录是否有写权限
    discuz管理中心无法登陆
    在Windows 7下面IIS7的安装和 配置ASP的正确方法
    window.open
    linux下的vmware虚拟机如何回收虚拟磁盘空间
    CentOS7 安装lamp 3分钟脚本
    pyhon 编译C++安装需要 c99 模式
    条件判断
    python字符串杂项
    RIPv1&v2
  • 原文地址:https://www.cnblogs.com/z1141000271/p/12703483.html
Copyright © 2011-2022 走看看