[LeetCode每日1题][中等] 1162. 地图分析

题目

1162. 地图分析 - 力扣(LeetCode)
在这里插入图片描述

DFS解法

class Solution
{
    int N;
    vector<vector<int>> dist; // 存放结点到陆地的最短距离
    vector<vector<int>> *grid;

public:
    int maxDistance(vector<vector<int>> &grid)
    {
        this->grid = &grid;
        N = grid.size();
        dist = vector<vector<int>>(N, vector<int>(N, -1)); // 初始化一个二维vector
        for (int i = 0; i < N; i++)
        {
            for (int j = 0; j < N; j++)
            {
                if (grid[i][j])
                {
                    dfs(i, j, 0); // 找到第一个陆地,开始dfs
                    break;
                }
            }
        }
        int max_dist = INT_MIN;
        for (auto i : dist)
        {
            for (auto j : i)
            {
                if (max_dist < j)
                    max_dist = j; // 找最大值
            }
        }
        return max_dist ? max_dist : -1;
    }
    void dfs(int i, int j, int step)
    {
        if ((*grid)[i][j])
        {
            step = 0; // 遇到陆地,重置step = 0, 接下来可能会出现回溯
        }
        if (dist[i][j] > step || dist[i][j] == -1) // 如果当前走法比历史走法更优
        {
            dist[i][j] = step++; // 更新为当前走法
            if (i > 0)
                dfs(i - 1, j, step); // 往上走
            if (j > 0)
                dfs(i, j - 1, step); // 往左走
            if (i < N - 1)
                dfs(i + 1, j, step); // 往下走
            if (j < N - 1)
                dfs(i, j + 1, step); // 往右走
        }
    }
};

多源BFS解法

class Solution
{
    struct Point
    {
        int x;
        int y;
    };
    int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, -1, 0, 1};
    queue<Point> q;
    const static int N = 101;
    int dist[N][N];
    int INF = 1E6;

public:
    int maxDistance(vector<vector<int>> &grid)
    {
        int size = grid.size();
        for (int i = 0; i < size; i++)
        {
            for (int j = 0; j < size; j++)
            {
                if (grid[i][j])
                {
	                // 所有陆地作为一个超级源点
                    q.push({i, j});
                    dist[i][j] = 0;
                }
                else
                {
                    dist[i][j] = INF;
                }
            }
        }
        while (!q.empty())
        {
            auto p = q.front();
            q.pop();
            for (int i = 0; i < 4; i++)
            {
                int nx = p.x + dx[i], ny = p.y + dy[i];
                if (nx >= 0 && nx < size && ny >= 0 && ny < size)
                {
                    if (dist[nx][ny] > dist[p.x][p.y] + 1)
                    {
                        dist[nx][ny] = dist[p.x][p.y] + 1;
                        q.push({nx, ny}); // 节点被更新,可能影响周围结点,入队
                    }
                }
            }
        }
        int _max = -1;
        for (int i = 0; i < size; i++)
        {
            for (int j = 0; j < size; j++)
            {
                if (!grid[i][j])
                {
                    _max = max(_max, dist[i][j]);
                }
            }
        }
        return _max == INF ? -1 : _max;
    }
};

DP法

class Solution {
public:
    static constexpr int MAX_N = 100 + 5;
    static constexpr int INF = int(1E6);
    
    int f[MAX_N][MAX_N];
    int n;

    int maxDistance(vector<vector<int>>& grid) {
        this->n = grid.size();
        vector<vector<int>>& a = grid;

        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < n; ++j) {
                f[i][j] = (a[i][j] ? 0 : INF);
            }
        }

        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < n; ++j) {
                if (a[i][j]) continue;
               	// 考虑更新值来自左或者上的情况,先dp一次
                if (i - 1 >= 0) f[i][j] = min(f[i][j], f[i - 1][j] + 1);
                if (j - 1 >= 0) f[i][j] = min(f[i][j], f[i][j - 1] + 1);
            }
        }

        for (int i = n - 1; i >= 0; --i) {
            for (int j = n - 1; j >= 0; --j) {
                if (a[i][j]) continue;
                // 在上个for循环的基础上,考虑更新值来自右或者下的情况,再dp一次
                if (i + 1 < n) f[i][j] = min(f[i][j], f[i + 1][j] + 1);
                if (j + 1 < n) f[i][j] = min(f[i][j], f[i][j + 1] + 1);
            }
        }

        int ans = -1;
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < n; ++j) {
                if (!a[i][j]) {
                    ans = max(ans, f[i][j]);
                }
            }
        }

        if (ans == INF) return -1;
        else return ans;
    }
};

作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/as-far-from-land-as-possible/solution/di-tu-fen-xi-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

参考

地图分析 - 地图分析 - 力扣(LeetCode)

posted @ 2020-03-29 15:19  zaqny  阅读(201)  评论(0编辑  收藏  举报