LeetCode 水位上升的泳池中游泳(广度优先搜索)

版权声明:本文为博主原创文章,博客地址:https://blog.csdn.net/qq_41855420,未经博主允许不得转载。 https://blog.csdn.net/qq_41855420/article/details/90067284

在一个 N x N 的坐标方格 grid 中,每一个方格的值 grid[i][j] 表示在位置 (i,j) 的平台高度。

现在开始下雨了。当时间为 t 时,此时雨水导致水池中任意位置的水位为 t 。你可以从一个平台游向四周相邻的任意一个平台,但是前提是此时水位必须同时淹没这两个平台。假定你可以瞬间移动无限距离,也就是默认在方格内部游动是不耗时的。当然,在你游泳的时候你必须待在坐标方格里面。

你从坐标方格的左上平台 (0,0) 出发。最少耗时多久你才能到达坐标方格的右下平台 (N-1, N-1)?

示例 1:

输入: [[0,2],[1,3]]
输出: 3
解释:
时间为0时,你位于坐标方格的位置为 (0, 0)。
此时你不能游向任意方向,因为四个相邻方向平台的高度都大于当前时间为 0 时的水位。

等时间到达 3 时,你才可以游向平台 (1, 1). 因为此时的水位是 3,坐标方格中的平台没有比水位 3 更高的,所以你可以游向坐标方格中的任意位置

示例2:

输入: [[0,1,2,3,4],[24,23,22,21,5],[12,13,14,15,16],[11,17,18,19,20],[10,9,8,7,6]]
输入: 16
解释:
 0  1  2  3  4
24 23 22 21  5
12 13 14 15 16
11 17 18 19 20
10  9  8  7  6
最终的路线用加粗进行了标记。
我们必须等到时间为 16,此时才能保证平台 (0, 0) 和 (4, 4) 是连通的

提示:

2 <= N <= 50.
grid[i][j] 位于区间 [0, ..., N*N - 1] 内。

\color{blue}{思路分析:} 说白了这道题就是让我们寻找一条路径从(0, 0)到(gridSize - 1, gridSize - 1),并且这条路径中最高的平台高度达到所有路径中的最小值。如果我们每次都采取贪心策略,取最小的节点高度,蛋式这种简单的策略是通不过的。我们可以使用类似分支限界法的做法,建立一个优先队列,对下一步即将经过的点进行由低到高的排序,这样每次尽可能选择的最低的,当选择这种最低的无法到达终点返回继续进行搜索。起始这就是广度优先搜索的升级版,

struct cmp {
    //排序规则,first由高到低
    bool operator()(const pair<int,int> & x, const pair<int,int> & y) {
        return x.first > y.first;
    }
};

class Solution {
public:
    int swimInWater(vector<vector<int>>& grid) {
        int minRes = 0, gridSize = grid.size();
        priority_queue<pair<int,int>,vector<pair<int,int>>,cmp> pq;//优先队列,队头放置高度最低的点
        vector<vector<bool>> visited(gridSize, vector<bool>(gridSize, false));//用于标记访问过的点
        vector<pair<int, int>> directions = { {1, 0}, {0, 1}, {-1, 0}, {0, -1} };//上下左右四个方向
        pq.push({0,0});//放入起始节点
        visited[0][0] = true;
        while(!pq.empty()){
            //每次获取当前队头(高度最小的点)
            pair<int,int> front = pq.top();
            pq.pop();
            int row = front.second / gridSize;
            int col = front.second % gridSize;
            minRes = max(minRes, grid[row][col]);//更新最小的结果高度
            //检查是否达到终点
            if(row == gridSize - 1 && col == gridSize - 1){
                break;
            }
            //上下左右四个方向进行搜索下一个未访问过的点
            for (auto &direction : directions) {
                int nextRow = row + direction.first;
                int nextCol = col + direction.second;
                //下一个节点不能出界或者已经访问过
                if(nextRow >= 0 && nextRow < gridSize && nextCol >= 0 && nextCol < gridSize && !visited[nextRow][nextCol]){
                    visited[nextRow][nextCol] = true;
                    pq.push({grid[nextRow][nextCol], nextRow * gridSize + nextCol});
                }
            }
        }
        return minRes;
    }
};

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_41855420/article/details/90067284