1. 程式人生 > 其它 >778 水位上升的泳池中游泳

778 水位上升的泳池中游泳

技術標籤:LeetCode

題目描述:
在一個 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] 的排列。

方法1:
主要思路:解題彙總連結
(1)二分;
(2)找出原陣列中的最大值和最小值作為二分的範圍;
(3)每次找出一箇中間值,判斷該值下是否能夠獲得到達終點,進一步縮小範圍;

class Solution {
public:
	//判斷限制值mid下是否能夠到達終點
    bool check(vector<vector<int>>&grid,
const int& mid,int row,int col,vector<vector<bool>>&sign){ if(row==grid.size()-1&&col==grid[0].size()-1){ if(grid.back().back()>mid){ return false; } return true; } sign[row][col]=true; if(grid[row][col]>mid){ sign[row][col]=true; return false; } if(row>0&&!sign[row-1][col]){ if(check(grid,mid,row-1,col,sign)){ return true; } } if(row+1<grid.size()&&!sign[row+1][col]){ if(check(grid,mid,row+1,col,sign)){ return true; } } if(col>0&&!sign[row][col-1]){ if(check(grid,mid,row,col-1,sign)){ return true; } } if(col+1<grid[0].size()&&!sign[row][col+1]){ if(check(grid,mid,row,col+1,sign)){ return true; } } return false; } int swimInWater(vector<vector<int>>& grid) { //確定最大值和最下值,既二分的範圍 int left=0; int right=0; for(vector<int>&vec:grid){ for(int& i:vec){ right=max(right,i); } } int res=0; //二分 while(left<=right){ int mid=left+(right-left)/2; vector<vector<bool>> sign(grid.size(),vector<bool>(grid[0].size(),false)); if(check(grid,mid,0,0,sign)){ right=mid-1; res=mid; } else{ left=mid+1; } } return res; } };

方法2:
主要思路:
(1)優先佇列;
(2)每次將能夠到達的位置壓入到優先佇列中,最小堆,每次堆頂的元素即為當前所有位置中值最下的結點位置;
(3)然後重新判讀能否有新的能夠到達的位置壓入佇列中;
(4)對於訪問過的位置,使用最大值INT_MAX進行標識;

class Solution {
public: 
    struct cmp{//比較函式
        bool operator()(vector<int>&lhs,vector<int>&rhs) {
            return lhs[0]>rhs[0];
        }
    };
    int swimInWater(vector<vector<int>>& grid) {
        priority_queue<vector<int>,vector<vector<int>>,cmp> q;
        q.push({grid[0][0],0,0});//初始化
        int rows=grid.size(),cols=grid[0].size();
        int res=0;
        while(!q.empty()){
            int cur_v=q.top()[0];
            int cur_r=q.top()[1];
            int cur_c=q.top()[2];
            q.pop();
            res=max(res,cur_v);//更新可能的結果
            if(cur_r==rows-1&&cur_c==cols-1){//達到了終點位置
                return res;
            }
            grid[cur_r][cur_c]=INT_MAX;//標識訪問過的位置
            //是否有新的位置加入
            if(cur_r>0&&grid[cur_r-1][cur_c]!=INT_MAX){
                q.push({grid[cur_r-1][cur_c],cur_r-1,cur_c});
            }
            if(cur_r+1<rows&&grid[cur_r+1][cur_c]!=INT_MAX){
                q.push({grid[cur_r+1][cur_c],cur_r+1,cur_c});
            }
            if(cur_c>0&&grid[cur_r][cur_c-1]!=INT_MAX){
                q.push({grid[cur_r][cur_c-1],cur_r,cur_c-1});
            }
            if(cur_c+1<cols&&grid[cur_r][cur_c+1]!=INT_MAX){
                q.push({grid[cur_r][cur_c+1],cur_r,cur_c+1});
            }
        }
        return res;
    }
};