LeetCode778 - 水位上升的泳池 (二分法BFS遍历、并查集)

题目:

You are given an n x n integer matrix grid where each value grid[i][j] represents the elevation at that point (i, j).

The rain starts to fall. At time t, the depth of the water everywhere is t. You can swim from a square to another 4-directionally adjacent square if and only if the elevation of both squares individually are at most t. You can swim infinite distances in zero time. Of course, you must stay within the boundaries of the grid during your swim.

Return the least time until you can reach the bottom right square (n - 1, n - 1) if you start at the top left square (0, 0).

在一个 n x n 的整数矩阵 grid 中,每一个方格的值 grid[i][j] 表示位置 (i, j) 的平台高度。

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

你从坐标方格的左上平台 (0,0) 出发。返回 你到达坐标方格的右下平台 (n-1, n-1) 所需的最少时间 。

思路:

一开始写的是朴素法,深搜遍历无二分。先构造一个水位变化之后的新数组(很慢),然后遍历寻找是否存在通往右下角的道路即可,超时。

然后用二分和递归深搜遍历,结果依然严重超时!后来思考原因,可能是因为深搜时递归调用太费时间。劈里啪啦敲了宽搜代码就过了,但是依然很慢。过程中出现了让人疑惑的现象:某些时候While的循环次数并不多,但是执行时间却很长。

后来尝试并查集,还有最小生成树的方法,拓展了思路。

题解:

深搜遍历+二分

class Solution {
private:
    bool answer=false;
public:
    int swimInWater(vector<vector<int>>& grid) {
        int t=-1, n=grid.size(), low=0, high=2500;
        int ret=3000;
        while(low<=high){
            t=(low+high)/2;
            cout<<"the current t is "<<t<<endl;
            answer=false;
            if(drown(grid,t,n)) ret=min(t,ret),high=t-1;
            else low=t+1;
        }
        return ret;
    }
    bool drown(vector<vector<int>> grid, int t, int n){
        vector<vector<int>> cur(n,vector<int>(n));
        vector<vector<bool>> been(n,vector<bool>(n));
        for(int i=0;i<n;++i){
            for(int j=0;j<n;++j){
                cur[i][j]=max(0,grid[i][j]-t);
                been[i][j]=false;
            }
        }
        search(0,0,n,been,cur);
        if(answer==true) return true;
        return false;
    }
    void search(int i, int j, int n, vector<vector<bool>>& been, vector<vector<int>> cur){
        if(i>=n || j>=n || i<0 || j<0 || been[i][j]==true || cur[i][j]!=0) return;
        if(i==n-1 && j==n-1) {answer=true; return;}
        been[i][j]=true;
        search(i,j-1,n,been,cur);
        search(i-1,j,n,been,cur);
        search(i,j+1,n,been,cur);
        search(i+1,j,n,been,cur);
        return;
    }
};

宽搜遍历+二分

class Solution {
private:
    int n;
    int direct_x[5]={1,-1,0,0};
    int direct_y[5]={0,0,1,-1};
public:
    int swimInWater(vector<vector<int>>& grid) {
        n=grid.size();
        int low=0, high=2500, t=-1, answer=10000;
        while(low<=high){
            t=(low+high)/2;
            cout<<"current t is "<<t;
            if(search(grid, t)) {
                high=t-1;
                answer=min(t,answer);
            }
            else low=t+1;
        }
        return answer;
    }

    bool search(vector<vector<int>> grid, int t){
        vector<vector<bool>> visited(n,vector<bool>(n,0));
        pair<int,int> p;
        queue<pair<int,int>> q;
        q.push({0,0});  // the top-left corner(starting point)
        while(!q.empty()){
            cout<<"search\n";
            p=q.front(), q.pop();  printf("  (%d,%d)\n",p.first,p.second);
            if(p.first<0 || p.first>=n || p.second<0 || p.second>=n) continue;
            if(visited[p.first][p.second]==true || grid[p.first][p.second]-t>0) continue;
            else{
                visited[p.first][p.second]=true;
                if(p.first==n-1 && p.second==n-1) return true;
                for(int i=0;i<=4;i++)   q.push({p.first+direct_x[i],p.second+direct_y[i]});
            }
        }
        return false;
    }

};

并查集

未完待续~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值