• 778. Swim in Rising Water


    问题:

    给定一个N*N正方形区域的海拔。

    一个人从[0,0]起向终点[N,N]前进,

    下雨每单位时间,下一单位海拔的水。

    只有当人所在周围的水位上升到海拔的位置,这个人才能向周围游动。

    求要到达终点,至少要经过多长时间。(不考虑游泳速度。只考虑下雨海拔满足的时间)

    Example 1:
    Input: [[0,2],[1,3]]
    Output: 3
    Explanation:
    At time 0, you are in grid location (0, 0).
    You cannot go anywhere else because 4-directionally adjacent neighbors have a higher elevation than t = 0.
    You cannot reach point (1, 1) until time 3.
    When the depth of water is 3, we can swim anywhere inside the grid.
    
    Example 2:
    Input: [[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]]
    Output: 16
    Explanation:
     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
    The final route is marked in bold.
    We need to wait until time 16 so that (0, 0) and (4, 4) are connected.
    
    Note:
    2 <= N <= 50.
    grid[i][j] is a permutation of [0, ..., N*N - 1].
    

      

    解法:

    解法一:并查集(Disjoint Set)

    使用 i*N+j。代表某个坐标点。作为并查集操作对象。

    每次判断:起点[0,0]终点[N,N]是否联通

    若没有:遍历正方形所有区域,

    若某个点的grid值<当前时间res

    则判断其右边和下面的点,是否也<当前时间res,则说明此时水的海拔已经漫过这些点,将这些点merge

    每次时间递增res++

    代码参考:

     1 class Solution {
     2 public:
     3     int swimInWater(vector<vector<int>>& grid) {
     4         int N=grid.size();
     5         DisjointSet DS(N*N);
     6         int res=0;
     7         while(!DS.isConnected(0, N*N-1)) {
     8             for(int i=0; i<N; i++) {
     9                 for(int j=0; j<N; j++) {
    10                     if(grid[i][j]>res) continue;
    11                     if(i+1 < N && grid[i+1][j] <= res) DS.merge(N*i+j, N*(i+1)+j);
    12                     if(j+1 < N && grid[i][j+1] <= res) DS.merge(N*i+j, N*i+j+1);
    13                 }
    14             }
    15             res++;
    16         }
    17         return res-1;
    18     }
    19 };

    并查集类 代码参考:

     1 class DisjointSet {
     2 public:
     3     DisjointSet(int n):root(n,0), rank(n,0) {
     4         for(int i=0; i<n; i++) {
     5             root[i]=i;
     6         }
     7     }
     8     int find(int i) {
     9         if(root[i]!=i) {
    10             root[i] = find(root[i]);
    11         }
    12         return root[i];
    13     }
    14     bool merge(int x, int y) {
    15         int x_root=find(x);
    16         int y_root=find(y);
    17         if(x_root==y_root) return false;
    18         if(rank[x_root] > rank[y_root]) {
    19             root[y_root] = x_root;
    20         } else if(rank[y_root] > rank[x_root]) {
    21             root[x_root] = y_root;
    22         } else {
    23             root[y_root] = x_root;
    24             rank[x_root]++;
    25         }
    26         return true;
    27     }
    28     bool isConnected(int x, int y) {
    29         int x_root=find(x);
    30         int y_root=find(y);
    31         return x_root==y_root;
    32     }
    33 private:
    34     vector<int> root;
    35     vector<int> rank;
    36 };
  • 相关阅读:
    BZOJ 3236 AHOI 2013 作业 莫队算法
    使用再哈希算法查找元素
    冰雪奇缘--用爱酿就一部经典
    Scrapy系列教程(2)------Item(结构化数据存储结构)
    html学习笔记二
    知方可补不足~sqlserver中触发器的使用
    我心中的核心组件(可插拔的AOP)~调度组件quartz.net
    EF架构~为BulkInsert引入SET IDENTITY_INSERT ON功能
    知方可补不足~sqlserver中使用sp_who查看sql的进程
    知方可补不足~为千万级数据表加索引
  • 原文地址:https://www.cnblogs.com/habibah-chang/p/13470426.html
Copyright © 2020-2023  润新知