地图分析

你现在手里有一份大小为 N x N 的『地图』(网格) grid,上面的每个『区域』(单元格)都用 0 和 1 标记好了。其中 0 代表海洋,1 代表陆地,你知道距离陆地区域最远的海洋区域是是哪一个吗?请返回该海洋区域到离它最近的陆地区域的距离。

我们这里说的距离是『曼哈顿距离』( Manhattan Distance):(x0, y0) 和 (x1, y1) 这两个区域之间的距离是 |x0 - x1| + |y0 - y1| 。

如果我们的地图上只有陆地或者海洋,请返回 -1。

示例 1:

1  0  1

0  0  0

1  0  1

输入:[[1,0,1],[0,0,0],[1,0,1]]
输出:2
解释:
海洋区域 (1, 1) 和所有陆地区域之间的距离都达到最大,最大距离为 2。

示例 2:

1  0  0

0  0  0

0  0  0

输入:[[1,0,0],[0,0,0],[0,0,0]]
输出:4
解释:
海洋区域 (2, 2) 和所有陆地区域之间的距离都达到最大,最大距离为 4。
 

提示:

1 <= grid.length == grid[0].length <= 100
grid[i][j] 不是 0 就是 1

class Solution {
public:
    int maxDistance(vector<vector<int>>& grid) {
        int n = grid.size();
        int dp[n][n];
        int INF = 201;
        int ans = -1;
        
        for(int i = 0; i < n; i++){
            for(int j = 0; j < n; j++){
                int left;
                int up;
                
                if(grid[i][j] == 0){
                    if(i == 0) up = INF;
                    else if(grid[i-1][j] == 1) up = 1;
                    else up = dp[i-1][j] + 1;

                    if(j == 0) left = INF;
                    else if(grid[i][j-1] == 1) left = 1;
                    else left = dp[i][j-1] + 1;

                    dp[i][j] = min(left,up);
                }
                else{
                    dp[i][j] = INF;
                }
            }
        }

        for(int i = n-1; i >= 0; i--){
            for(int j = n-1; j >= 0; j--){
                int right;
                int down;
                
                if(grid[i][j] == 0){
                    if(i == n-1) down = INF;
                    else if(grid[i+1][j] == 1) down = 1;
                    else down = dp[i+1][j] + 1;

                    if(j == n-1) right = INF;
                    else if(grid[i][j+1] == 1) right = 1;
                    else right = dp[i][j+1] + 1;

                    dp[i][j] = min(dp[i][j],min(right,down));
                }
                else{
                    dp[i][j] = INF;
                }
            }
        }

        for(int i = 0; i < n; i++){
            for(int j = 0; j < n; j++){
                if(grid[i][j] == 0){
                    ans = max(dp[i][j], ans);
                }

            }
        }

        return ans>=INF?-1:ans;
    }
};

解题思路:还记得机器人走不同路径那道题不?其实这个跟那个差不多,也可以用dp做。只不过是两遍dp,一遍从左上角到右下角,一遍从右下角到左上角。然后再遍历一遍dp数组,在海洋节点中找到最大距离就好了。

 需要注意的是,两遍dp不能分开,必须用一个dp数组。

原因是:

0    1

0    0

如果用两个dp的话,那么在计算第二个dp的时候,图中右下角的最小距离可能是2,因为它计算的时候只用到右边和下边的信息,而没有用到上面的信息。

这样就导致了上图左下角在计算距离的时候不能利用右上角的信息,因为如果共用一个dp,那么右下角在计算的时候就不光计算下边和右边的距离,还要跟本身在第一遍dp的时候记载的距离进行比较,而第一遍dp记载的距离就包含了来自右上角的信息,所以右下角在第二遍dp的时候距离才会被计算为1,也只有当右下角用到了右上角的信息的时候,左下角才能通过右下角用到右上角的信息。

猜你喜欢

转载自www.cnblogs.com/olajennings/p/12596112.html