▶ 给定方阵 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( * n - , max(grid[][], grid[n - ][n - ])) - , rp = n * n, mp = (lp + rp) / ; lp < rp && mp > lp; mp = (lp + rp) / )
  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({ , }), table[][] = true; !qq.empty();)
  25. {
  26. temp = qq.front(), qq.pop(), row = temp[], col = temp[];
  27. if (row == n - && col == n - )
  28. return true;
  29.  
  30. if (row > && grid[row - ][col] <= time && !table[row - ][col])// up
  31. qq.push({ row - , col }), table[row - ][col] = true;
  32. if (col > && grid[row][col - ] <= time && !table[row][col - ])// left
  33. qq.push({ row, col - }), table[row][col - ] = true;
  34. if (row < n - && grid[row + ][col] <= time && !table[row + ][col])// down
  35. qq.push({ row + , col }), table[row + ][col] = true;
  36. if (col < n - && grid[row][col + ] <= time && !table[row][col + ])// right
  37. qq.push({ row, col + }), table[row][col + ] = 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[][], rp = n * n - ; lp < rp;)
  9. {
  10. mp = lp + (rp - lp) / ;
  11. if (valid(grid, mp))
  12. rp = mp;
  13. else
  14. lp = mp + ;
  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({ -, , , , - });
  22. vector<vector<bool>> visited(n, vector<bool>(n, ));
  23. return dfs(grid, visited, dir, waterHeight, , , 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 = ; i < ; ++i)
  30. {
  31. r = row + dir[i], c = col + dir[i + ];
  32. if (r >= && r < n && c >= && c < n && visited[r][c] == false && grid[r][c] <= waterHeight)
  33. {
  34. if (r == n - && c == n - )
  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, , , , dp);
  9. return dp[m - ][m - ];
  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 = ; i < direction.size(); i++)
  19. {
  20. x = row + direction[i][], y = col + direction[i][];
  21. if (x >= && x < m && y >= && y < m)
  22. helper(grid, x, y, dp[row][col], dp);
  23. }
  24. }
  25. vector<vector<int>> direction = { { -, },{ , },{ , },{ , - } };
  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({ -, , , , - });
  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[][] = true, ans = max(grid[][], grid[n - ][n - ]), pq.push({ ans, , }); !pq.empty();)
  13. {
  14. cur = pq.top(),pq.pop(), ans = max(ans, cur[]);
  15. for (i = ; i < ; i++)
  16. {
  17. r = cur[] + dir[i], c = cur[] + dir[i + ];
  18. if (r >= && r < n && c >= && c < n && visited[r][c] == false)
  19. {
  20. visited[r][c] = true;
  21. if (r == n - && c == n - )
  22. return ans;
  23. pq.push({ grid[r][c], r, c });
  24. }
  25. }
  26. }
  27. return -;
  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({ -, , , , - });
  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[][] = true, ans = max(grid[][], grid[n - ][n - ]), pq.push({ ans, , }); !pq.empty();)
  15. {
  16. cur = pq.top(), pq.pop(), ans = max(ans, cur[]);
  17. for (myq.push({ cur[], cur[] }); !myq.empty();)
  18. {
  19. p = myq.front(), myq.pop();
  20. if (p.first == n - && p.second == n - )
  21. return ans;
  22. for (i = ; i < ; ++i)
  23. {
  24. r = p.first + dir[i], c = p.second + dir[i + ];
  25. if (r >= && r < n && c >= && c < n && visited[r][c] == )
  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 -;
  37. }
  38. };

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

  1. {
  2. {, , , , , , , , , , , , , , , , , , , },
  3. { , , , , , , , , , , , , , , , , , , , },
  4. { , , , , , , , , , , , , , , , , , , , },
  5. { , , , , , , , , , , , , , , , , , , , },
  6. { , , , , , , , , , , , , , , , , , , , },
  7. { , , , , , , , , , , , , , , , , , , , },
  8. { , , , , , , , , , , , , , , , , , , , },
  9. { , , , , , , , , , , , , , , , , , , , },
  10. { , , , , , , , , , , , , , , , , , , , },
  11. { , , , , , , , , , , , , , , , , , , , },
  12. { , , , , , , , , , , , , , , , , , , , },
  13. { , , , , , , , , , , , , , , , , , , , },
  14. { , , ,, , , , , , , , , , , , , , , , },
  15. { , , , , , , , , , , , , , , , , , , , },
  16. { , , , , , , , , , , , , , , , , , , , },
  17. { , , , , , , , , , , , , , , , , , , , },
  18. { , , , , , , , , , , , , , , , , , , , },
  19. { , , , , , , , , , , , , , , , , , , , },
  20. { , , , , , , , , , , , , , , , , , , , },
  21. { , , , , , , , , , , , , , , , , , , , }
  22. };

778. Swim in Rising Water的更多相关文章

  1. 【LeetCode】778. Swim in Rising Water 水位上升的泳池中游泳(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 题目地址: https://leetcode.com/problems/swim-in- ...

  2. 【leetcode】778. Swim in Rising Water

    题目如下: 解题思路:本题题干中提到了一个非常重要的前提:"You can swim infinite distance in zero time",同时也给了一个干扰条件,那就是 ...

  3. LeetCode 778. Swim in Rising Water

    题目链接:https://leetcode.com/problems/swim-in-rising-water/ 题意:已知一个n*n的网格,初始时的位置为(0,0),目标位置为(n-1,n-1),且 ...

  4. [Swift]LeetCode778. 水位上升的泳池中游泳 | Swim in Rising Water

    On an N x N grid, each square grid[i][j]represents the elevation at that point (i,j). Now rain start ...

  5. [LeetCode] Swim in Rising Water 在上升的水中游泳

    On an N x N grid, each square grid[i][j] represents the elevation at that point (i,j). Now rain star ...

  6. LeetCode All in One题解汇总(持续更新中...)

    突然很想刷刷题,LeetCode是一个不错的选择,忽略了输入输出,更好的突出了算法,省去了不少时间. dalao们发现了任何错误,或是代码无法通过,或是有更好的解法,或是有任何疑问和建议的话,可以在对 ...

  7. 算法与数据结构基础 - 堆(Heap)和优先级队列(Priority queue)

    堆基础 堆(Heap)是具有这样性质的数据结构:1/完全二叉树 2/所有节点的值大于等于(或小于等于)子节点的值: 图片来源:这里 堆可以用数组存储,插入.删除会触发节点shift_down.shif ...

  8. All LeetCode Questions List 题目汇总

    All LeetCode Questions List(Part of Answers, still updating) 题目汇总及部分答案(持续更新中) Leetcode problems clas ...

  9. leetcode hard

    # Title Solution Acceptance Difficulty Frequency     4 Median of Two Sorted Arrays       27.2% Hard ...

随机推荐

  1. JAVA异常处理分析高级进界(下)

    既然Throwable是异常处理机制的核心,那么,我们就来分析下它的源码来看看它是如何实现的. 进行分析前,我们可以先想想如果让我们实现一个异常处理机制,我们需要它做什么? 1. 发生异常终止程序执行 ...

  2. CentOS下安装docker,docker-compose

    1.查看系统发行版本: lsb_release -a 2.安装docker:Docker 是一个开源的应用容器引擎,可以让开发者打包他们的应用以及依赖包到一个轻量级.可移植的容器中,然后发布到任何流行 ...

  3. Linux jdk环境配置模板

    export JAVA_HOME=/opt/JAVA/jdk1.8.0_191export JRE_HOME=${JAVA_HOME}/jreexport CLASSPATH=.:${JAVA_HOM ...

  4. Xcode 7.0 Could not find developer disk image

    在使用Xcode 7的真机运行的时候, 出现Could not find developer disk image. 解决方法:先关闭Xcode.再从Xcode 6.4中,拷贝8.4 (12H141) ...

  5. 【LeetCode 144_二叉树_遍历】Binary Tree Preorder Traversal

    解法一:非递归 vector<int> preorderTraversal(TreeNode* root) { vector<int> res; if (root == NUL ...

  6. 201621123005《Java程序设计》第十次实验总结

    201621123005<Java程序设计>第十周学习总结 1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结异常相关内容. 2. 书面作业 1. 常用异常 1.1 自己 ...

  7. Linux 网络编程->epoll<-LT/ET模式整理(~相逢何必曾相识~)

    今天自己整理一下epoll,网上有很多经典的介绍,看了很多~收藏了很多~还是整理一下做个积累, 自己的东西好找~ 1. epoll 模型简介 epoll 是Linux I/O 多路复用接口 selec ...

  8. C/C++ 父子进程之间的文件描述符问题

    在C程序中,文件由文件指针或者文件描述符表示.ISO C的标准I/0库函数(fopen, fclose, fread, fwrite, fscanf, fprintf等)使用文件指针,UNIX的I/O ...

  9. 微信小程序页面跳转的四种方法

    wx.navigateTo({}) ,保留当前页面,跳转到应用内的某个页面,使用 wx.navigateBack 可以返回; 示例: 1 wx.navigateTo({ 2 url:'../test/ ...

  10. selenium-java,暂停功能

    暂停/开始应用程序 public class Common_method { public void kill_chromedriver(){ Runtime runtime=Runtime.getR ...