LeetCode/水位上升的泳池中游泳

在一个 n x n 的整数矩阵 grid 中,每一个方格的值 grid[i][j] 表示位置 (i, j) 的平台高度。
当开始下雨时,在时间为 t 时,水池中的水位为 t 。你可以从一个平台游向四周相邻的任意一个平台,但是前提是此时水位必须同时淹没这两个平台。
你从坐标方格的左上平台 (0,0) 出发。返回 你到达坐标方格的右下平台 (n-1, n-1) 所需的最少时间

一. 二分法+DFS

分析:时间是一个连续的量,随着时间增加最终肯定能达到目的地,这里是一个求最小的问题
初始化左边界为初始点的高度,右边界为最大高度,使用二分法加快求解
同时对二分的时间状态,判断能否连通至终点,这里使用深度优先搜索,对四个方向进行递归
边界条件为终点,同时每个时间状态要初始化一个visit二维数组记录走过的路径,用于防止折返无限递归

class Solution {
public:
    vector<vector<bool>> vis;
    vector<vector<int>> dir = {{0,1},{1,0},{-1,0},{0,-1}};
    int swimInWater(vector<vector<int>>& grid) {
        int left = grid[0][0];  int right = INT_MIN;
        for(auto &x:grid)
            for(int &y:x)
                right = max(right,y);
        int n = grid.size();
        vis.resize(n,vector<bool>(n));
        while(left<right){
            for(int i=0;i<n;i++)
                for(int j=0;j<n;j++) vis[i][j] = 0;
            int mid = (left+right)/2;
            //重新初始化访问记录
            if(judge(0,0,mid,grid)) right = mid;//找下界
            else left = mid + 1;
        }
        return right;
    }
    bool judge(int x,int y,int time,vector<vector<int>>& grid){
        int n = grid.size();
        if(x==n-1&&y==n-1) return true;//递归边界条件
        for(int i=0;i<4;i++){//四个方向递归
            int nx = x + dir[i][0]; int ny = y + dir[i][1];
            if(nx>=0&&ny>=0&&nx<n&ny<n&&!vis[nx][ny]&&grid[nx][ny]<=time){//限制条件
                vis[nx][ny] = true;//防止无限递归
                if(judge(nx,ny,time,grid)) return true;
            }
        }
        return false;
    }
};

二. kruskal+并查集

分析:随着时间流逝,各个台子被水覆盖,可以看做是新被激活的点,通过并查集操作,将其与其他被覆盖的点进行连通
若终点最后并入初始点的集合,则此时为满足条件的最小时间

class Solution {
public:
    vector<int> parent;
    vector<vector<int>> dir = {{0,1},{1,0},{-1,0},{0,-1}};
    int n;
    int find(int i){ //寻找集合首索引,即集合的唯一标识符
        if (parent[i] != i) parent[i] = find(parent[i]);  //如果自己不是,递归寻找且更新索引
        return parent[i];
    }
    void unions(int i ,int j){
        parent[find(i)] = parent[find(j)]; 
    }
    bool query(int i,int j){
        return find(i)==find(j);
    }
    int swimInWater(vector<vector<int>>& grid) {
        n = grid.size();
        parent.resize(n*n);
        for(int i=0;i<parent.size();i++) parent[i] = i;//二维矩阵一维化

        vector<vector<int>> priority(n*n,vector<int>(3));
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++){
                priority[getindex(i,j)][0]=grid[i][j];
                priority[getindex(i,j)][1]=i;
                priority[getindex(i,j)][2]=j;}
        sort(priority.begin(),priority.end());
        for(int i=0;i<priority.size();i++){//一定有解
            int cur =  priority[i][0];
            int x = priority[i][1];
            int y = priority[i][2];
            for(int i=0;i<4;i++){//四个方向进行连通判断
            int nx = x + dir[i][0]; int ny = y + dir[i][1];
            if(nx>=0&&ny>=0&&nx<n&ny<n&&grid[nx][ny]<=cur)//限制条件
                unions(getindex(x,y),getindex(nx,ny));
          }
          if(query(0,n*n-1)) return cur;
        }
        return 0;
    }
    int getindex(int i,int j){
        return i*n+j;
    }
};
posted @ 2023-04-14 03:40  失控D大白兔  阅读(20)  评论(0编辑  收藏  举报