• 778. Swim in Rising Water


    ▶ 给定方阵 grid,其元素的值为 D0n-1,代表网格中该点处的高度。现在网格中开始积水,时刻 t 的时候所有值不大于 t 的格点被水淹没,当两个相邻格点(上下左右四个方向)的值都不超过 t 的时候我们称他们连通,即可以通过游泳到达,请问能将主对角两顶点((0, 0) 和 (n-1, n-1))连通的最小时刻是多少?例如 下图的最小连通时间为 16 。

      

    ● 自己的代码,22 ms,简单 BFS,普通队列

     1 class Solution
     2 {
     3 public:
     4     int swimInWater(vector<vector<int>>& grid)//set a binary search to find a proper moment
     5     {
     6         const int n = grid.size();
     7         int lp, rp, mp;
     8         for (lp = max(2 * n - 2, max(grid[0][0], grid[n - 1][n - 1])) - 1, rp = n * n, mp = (lp + rp) / 2; lp < rp && mp > lp; mp = (lp + rp) / 2)
     9         {                       // 时间最小是 2n-2,最大是 n^2-1
    10             if (swim(grid, mp))
    11                 rp = mp;
    12             else
    13                 lp = mp;
    14         }
    15         return rp;
    16     }
    17     bool swim(vector<vector<int>>& grid, int time)// swimming at the moment 'time', can I reach the point (n-1, n-1)?
    18     {
    19         const int n = grid.size();
    20         vector<vector<bool>> table(n, vector<bool>(n, false));
    21         queue<vector<int>> qq;
    22         vector<int> temp;
    23         int row, col;
    24         for (qq.push({ 0, 0 }), table[0][0] = true; !qq.empty();)
    25         {
    26             temp = qq.front(), qq.pop(), row = temp[0], col = temp[1];
    27             if (row == n - 1 && col == n - 1)
    28                 return true;
    29 
    30             if (row > 0 && grid[row - 1][col] <= time && !table[row - 1][col])// up
    31                 qq.push({ row - 1, col }), table[row - 1][col] = true;
    32             if (col > 0 && grid[row][col - 1] <= time && !table[row][col - 1])// left
    33                 qq.push({ row, col - 1 }), table[row][col - 1] = true;
    34             if (row < n - 1 && grid[row + 1][col] <= time && !table[row + 1][col])// down
    35                 qq.push({ row + 1, col }), table[row + 1][col] = true;
    36             if (col < n - 1 && grid[row][col + 1] <= time && !table[row][col + 1])// right
    37                 qq.push({ row, col + 1 }), table[row][col + 1] = true;
    38         }
    39         return false;
    40     }
    41 };

    ● 大佬的代码,13 ms,DFS,注意这里使用了一个数组 dir 来决定搜索方向,比较有趣的用法

     1 class Solution
     2 {
     3 public:
     4     int swimInWater(vector<vector<int>>& grid)
     5     {
     6         const int n = grid.size();
     7         int lp, rp, mp;
     8         for (lp = grid[0][0], rp = n * n - 1; lp < rp;) 
     9         {
    10             mp = lp + (rp - lp) / 2;
    11             if (valid(grid, mp))
    12                 rp = mp;
    13             else
    14                 lp = mp + 1;
    15         }
    16         return lp;
    17     }
    18     bool valid(vector<vector<int>>& grid, int waterHeight)
    19     {
    20         const int n = grid.size();
    21         const vector<int> dir({ -1, 0, 1, 0, -1 });
    22         vector<vector<bool>> visited(n, vector<bool>(n, 0));        
    23         return dfs(grid, visited, dir, waterHeight, 0, 0, n);
    24     }
    25     bool dfs(vector<vector<int>>& grid, vector<vector<bool>>& visited, vector<int>& dir, int waterHeight, int row, int col, int n)
    26     {
    27         int i, r, c;
    28         visited[row][col] = true;
    29         for (i = 0; i < 4; ++i)
    30         {
    31             r = row + dir[i], c = col + dir[i + 1];
    32             if (r >= 0 && r < n && c >= 0 && c < n && visited[r][c] == false && grid[r][c] <= waterHeight)
    33             {
    34                 if (r == n - 1 && c == n - 1)
    35                     return true;
    36                 if (dfs(grid, visited, dir, waterHeight, r, c, n))
    37                     return true;
    38             }
    39         }
    40         return false;
    41     }
    42 };

    ● 大佬的代码,185 ms,DP + DFS,维护一个方阵 dp,理解为“沿着当前搜索路径能够到达某一格点的最小时刻”,初始假设 dp = [INT_MAX] ,即所有的格点都要在 INT_MAX 的时刻才能到达,深度优先遍历每个点,不断下降每个点的值(用该点原值和用于遍历的临时深度值作比较,两者都更新为他们的较小者)

     1 class Solution
     2 {
     3 public:
     4     int swimInWater(vector<vector<int>> &grid)
     5     {
     6         const int m = grid.size();
     7         vector<vector<int>> dp(m, vector<int>(m, INT_MAX));
     8         helper(grid, 0, 0, 0, dp);
     9         return dp[m - 1][m - 1];
    10     }
    11     void helper(vector<vector<int>> &grid, int row, int col, int deep, vector<vector<int>> &dp)
    12     {
    13         const int m = grid.size();
    14         int i, x, y;
    15         deep = max(deep, grid[row][col]);
    16         if (dp[row][col] <= deep)
    17             return;
    18         for (dp[row][col] = deep, i = 0; i < direction.size(); i++)
    19         {
    20             x = row + direction[i][0], y = col + direction[i][1];
    21             if (x >= 0 && x < m && y >= 0 && y < m)
    22                 helper(grid, x, y, dp[row][col], dp);
    23         }
    24     }
    25     vector<vector<int>> direction = { { -1, 0 },{ 1, 0 },{ 0, 1 },{ 0, -1 } };
    26 };

    ● 大佬的代码,18 ms,DFS,优先队列,Dijkstra算法,相当于在搜索队列中,总是优先研究最小时刻的点

     1 class Solution
     2 {
     3 public:
     4     int swimInWater(vector<vector<int>>& grid)
     5     {
     6         const int n = grid.size();
     7         const vector<int> dir({ -1, 0, 1, 0, -1 });
     8         int ans, i, r, c;
     9         priority_queue<vector<int>, vector<vector<int>>, greater<vector<int>>> pq;
    10         vector<vector<bool>> visited(n, vector<bool>(n, false));
    11         vector<int> cur;
    12         for (visited[0][0] = true, ans = max(grid[0][0], grid[n - 1][n - 1]), pq.push({ ans, 0, 0 }); !pq.empty();)
    13         {
    14             cur = pq.top(),pq.pop(), ans = max(ans, cur[0]);
    15             for (i = 0; i < 4; i++)
    16             {
    17                 r = cur[1] + dir[i], c = cur[2] + dir[i + 1];
    18                 if (r >= 0 && r < n && c >= 0 && c < n && visited[r][c] == false)
    19                 {
    20                     visited[r][c] = true;
    21                     if (r == n - 1 && c == n - 1)
    22                         return ans;
    23                     pq.push({ grid[r][c], r, c });                    
    24                 }
    25             }
    26         }
    27         return -1;
    28     }
    29 };

    ● 大佬的代码,11 ms,使用那个 DP + DFS 解法的深度更新思路,把搜索方式换成 BFS

     1 class Solution
     2 {
     3 public:
     4     int swimInWater(vector<vector<int>>& grid)
     5     {
     6         const int n = grid.size();
     7         const vector<int> dir({ -1, 0, 1, 0, -1 });
     8         int ans, i, r, c;
     9         vector<vector<bool>> visited(n, vector<bool>(n, false));
    10         priority_queue<vector<int>, vector<vector<int>>, greater<vector<int>>> pq;
    11         vector<int> cur;         
    12         queue<pair<int, int>> myq;        
    13         pair<int, int> p;
    14         for (visited[0][0] = true, ans = max(grid[0][0], grid[n - 1][n - 1]), pq.push({ ans, 0, 0 }); !pq.empty();)
    15         {
    16             cur = pq.top(), pq.pop(), ans = max(ans, cur[0]);
    17             for (myq.push({ cur[1], cur[2] }); !myq.empty();)
    18             {
    19                 p = myq.front(), myq.pop();
    20                 if (p.first == n - 1 && p.second == n - 1) 
    21                     return ans;
    22                 for (i = 0; i < 4; ++i)
    23                 {
    24                     r = p.first + dir[i], c = p.second + dir[i + 1];
    25                     if (r >= 0 && r < n && c >= 0 && c < n && visited[r][c] == 0)
    26                     {
    27                         visited[r][c] = true;
    28                         if (grid[r][c] <= ans)
    29                             myq.push({ r, c });
    30                         else
    31                             pq.push({ grid[r][c], r, c });
    32                     }
    33                 }
    34             }
    35         }
    36         return -1;
    37     }
    38 };

    ▶ 附上一个测试数据,答案为 266

     1 { 
     2     {105, 209, 171, 91, 64, 394, 279, 11, 45, 84, 207, 321, 216, 197, 381, 377, 78, 19, 203, 198},
     3     { 141, 10, 335, 170, 265, 104, 338, 40, 397, 376, 346, 356, 212, 154, 280, 177, 247, 90, 87, 360 },
     4     { 99, 59, 242, 149, 344, 172, 276, 230, 133, 193, 284, 345, 46, 363, 30, 142, 295, 70, 224, 200 },
     5     { 251, 88, 379, 72, 319, 272, 243, 165, 180, 182, 387, 264, 23, 67, 137, 342, 125, 139, 144, 367 },
     6     { 94, 211, 151, 37, 290, 112, 343, 157, 300, 271, 260, 373, 369, 294, 289, 57, 44, 12, 20, 340 }, 
     7     { 220, 368, 186, 277, 181, 187, 273, 214, 315, 337, 328, 18, 231, 223, 331, 75, 275, 96, 135, 150 },
     8     { 202, 74, 27, 184, 399, 341, 49, 62, 261, 86, 314, 383, 302, 257, 61, 148, 268, 120, 36, 25 },
     9     { 15, 253, 285, 185, 226, 146, 126, 122, 83, 361, 110, 234, 183, 239, 52, 190, 152, 81, 136, 188 },
    10     { 39, 199, 358, 26, 301, 116, 32, 386, 29, 138, 393, 159, 102, 140, 370, 227, 282, 111, 5, 33 },
    11     { 189, 35, 132, 54, 210, 235, 28, 353, 281, 127, 318, 58, 100, 286, 384, 24, 307, 252, 80, 103 }, 
    12     { 244, 176, 124, 79, 161, 355, 218, 398, 392, 380, 225, 121, 178, 352, 329, 322, 167, 51, 313, 85 }, 
    13     { 107, 118, 351, 287, 324, 283, 48, 320, 82, 364, 357, 16, 219, 330, 89, 143, 241, 262, 71, 191 }, 
    14     { 95, 97, 3,7, 270, 249, 213, 339, 362, 298, 4, 258, 248, 390, 299, 306, 156, 164, 109, 229 }, 
    15     { 221, 9, 228, 160, 274, 263, 374, 147, 98, 63, 13, 41, 326, 396, 349, 372, 385, 317, 325, 266 },
    16     { 53, 131, 173, 312, 174, 114, 250, 119, 163, 22, 246, 92, 278, 365, 292, 215, 14, 304, 204, 73 },
    17     { 233, 323, 366, 130, 378, 305, 311, 93, 134, 217, 297, 327, 232, 194, 240, 1, 208, 6, 310, 47 }, 
    18     { 69, 101, 332, 195, 254, 236, 50, 166, 56, 168, 267, 17, 359, 347, 65, 316, 238, 296, 348, 222 },
    19     { 76, 123, 129, 293, 391, 2, 245, 108, 303, 38, 66, 55, 43, 256, 162, 60, 179, 77, 336, 21 },
    20     { 196, 388, 333, 395, 42, 382, 291, 237, 288, 375, 128, 145, 192, 158, 350, 259, 206, 34, 334, 255 }, 
    21     { 201, 175, 153, 68, 205, 155, 115, 269, 389, 169, 371, 308, 117, 31, 354, 8, 113, 309, 106, 0 }
    22 };
  • 相关阅读:
    【OpenCV学习】安防监控可疑走动报警
    【OpenCV学习】OpenMP并行化实例
    【OpenCV学习】cvConvert的使用
    【OpenCV学习】Fuzzy Logic模糊逻辑边缘提取
    C# 委托系列(一)将方法作为方法的参数
    关于dev的Gridview控件的行数据的颜色控制,根据不同的值设置不同颜色
    将gridcontrol导出到excel
    DataGridView中将某行设置为当前可见区域第一行
    如何获得窗体上控件相对于屏幕的位置?
    dev 控件 lookupedit 设置选项值
  • 原文地址:https://www.cnblogs.com/cuancuancuanhao/p/8419569.html
Copyright © 2020-2023  润新知