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

  

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

 class Solution
{
public:
int swimInWater(vector<vector<int>>& grid)//set a binary search to find a proper moment
{
const int n = grid.size();
int lp, rp, mp;
for (lp = max( * n - , max(grid[][], grid[n - ][n - ])) - , rp = n * n, mp = (lp + rp) / ; lp < rp && mp > lp; mp = (lp + rp) / )
{ // 时间最小是 2n-2,最大是 n^2-1
if (swim(grid, mp))
rp = mp;
else
lp = mp;
}
return rp;
}
bool swim(vector<vector<int>>& grid, int time)// swimming at the moment 'time', can I reach the point (n-1, n-1)?
{
const int n = grid.size();
vector<vector<bool>> table(n, vector<bool>(n, false));
queue<vector<int>> qq;
vector<int> temp;
int row, col;
for (qq.push({ , }), table[][] = true; !qq.empty();)
{
temp = qq.front(), qq.pop(), row = temp[], col = temp[];
if (row == n - && col == n - )
return true; if (row > && grid[row - ][col] <= time && !table[row - ][col])// up
qq.push({ row - , col }), table[row - ][col] = true;
if (col > && grid[row][col - ] <= time && !table[row][col - ])// left
qq.push({ row, col - }), table[row][col - ] = true;
if (row < n - && grid[row + ][col] <= time && !table[row + ][col])// down
qq.push({ row + , col }), table[row + ][col] = true;
if (col < n - && grid[row][col + ] <= time && !table[row][col + ])// right
qq.push({ row, col + }), table[row][col + ] = true;
}
return false;
}
};

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

 class Solution
{
public:
int swimInWater(vector<vector<int>>& grid)
{
const int n = grid.size();
int lp, rp, mp;
for (lp = grid[][], rp = n * n - ; lp < rp;)
{
mp = lp + (rp - lp) / ;
if (valid(grid, mp))
rp = mp;
else
lp = mp + ;
}
return lp;
}
bool valid(vector<vector<int>>& grid, int waterHeight)
{
const int n = grid.size();
const vector<int> dir({ -, , , , - });
vector<vector<bool>> visited(n, vector<bool>(n, ));
return dfs(grid, visited, dir, waterHeight, , , n);
}
bool dfs(vector<vector<int>>& grid, vector<vector<bool>>& visited, vector<int>& dir, int waterHeight, int row, int col, int n)
{
int i, r, c;
visited[row][col] = true;
for (i = ; i < ; ++i)
{
r = row + dir[i], c = col + dir[i + ];
if (r >= && r < n && c >= && c < n && visited[r][c] == false && grid[r][c] <= waterHeight)
{
if (r == n - && c == n - )
return true;
if (dfs(grid, visited, dir, waterHeight, r, c, n))
return true;
}
}
return false;
}
};

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

 class Solution
{
public:
int swimInWater(vector<vector<int>> &grid)
{
const int m = grid.size();
vector<vector<int>> dp(m, vector<int>(m, INT_MAX));
helper(grid, , , , dp);
return dp[m - ][m - ];
}
void helper(vector<vector<int>> &grid, int row, int col, int deep, vector<vector<int>> &dp)
{
const int m = grid.size();
int i, x, y;
deep = max(deep, grid[row][col]);
if (dp[row][col] <= deep)
return;
for (dp[row][col] = deep, i = ; i < direction.size(); i++)
{
x = row + direction[i][], y = col + direction[i][];
if (x >= && x < m && y >= && y < m)
helper(grid, x, y, dp[row][col], dp);
}
}
vector<vector<int>> direction = { { -, },{ , },{ , },{ , - } };
};

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

 class Solution
{
public:
int swimInWater(vector<vector<int>>& grid)
{
const int n = grid.size();
const vector<int> dir({ -, , , , - });
int ans, i, r, c;
priority_queue<vector<int>, vector<vector<int>>, greater<vector<int>>> pq;
vector<vector<bool>> visited(n, vector<bool>(n, false));
vector<int> cur;
for (visited[][] = true, ans = max(grid[][], grid[n - ][n - ]), pq.push({ ans, , }); !pq.empty();)
{
cur = pq.top(),pq.pop(), ans = max(ans, cur[]);
for (i = ; i < ; i++)
{
r = cur[] + dir[i], c = cur[] + dir[i + ];
if (r >= && r < n && c >= && c < n && visited[r][c] == false)
{
visited[r][c] = true;
if (r == n - && c == n - )
return ans;
pq.push({ grid[r][c], r, c });
}
}
}
return -;
}
};

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

 class Solution
{
public:
int swimInWater(vector<vector<int>>& grid)
{
const int n = grid.size();
const vector<int> dir({ -, , , , - });
int ans, i, r, c;
vector<vector<bool>> visited(n, vector<bool>(n, false));
priority_queue<vector<int>, vector<vector<int>>, greater<vector<int>>> pq;
vector<int> cur;
queue<pair<int, int>> myq;
pair<int, int> p;
for (visited[][] = true, ans = max(grid[][], grid[n - ][n - ]), pq.push({ ans, , }); !pq.empty();)
{
cur = pq.top(), pq.pop(), ans = max(ans, cur[]);
for (myq.push({ cur[], cur[] }); !myq.empty();)
{
p = myq.front(), myq.pop();
if (p.first == n - && p.second == n - )
return ans;
for (i = ; i < ; ++i)
{
r = p.first + dir[i], c = p.second + dir[i + ];
if (r >= && r < n && c >= && c < n && visited[r][c] == )
{
visited[r][c] = true;
if (grid[r][c] <= ans)
myq.push({ r, c });
else
pq.push({ grid[r][c], r, c });
}
}
}
}
return -;
}
};

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

 {
{, , , , , , , , , , , , , , , , , , , },
{ , , , , , , , , , , , , , , , , , , , },
{ , , , , , , , , , , , , , , , , , , , },
{ , , , , , , , , , , , , , , , , , , , },
{ , , , , , , , , , , , , , , , , , , , },
{ , , , , , , , , , , , , , , , , , , , },
{ , , , , , , , , , , , , , , , , , , , },
{ , , , , , , , , , , , , , , , , , , , },
{ , , , , , , , , , , , , , , , , , , , },
{ , , , , , , , , , , , , , , , , , , , },
{ , , , , , , , , , , , , , , , , , , , },
{ , , , , , , , , , , , , , , , , , , , },
{ , , ,, , , , , , , , , , , , , , , , },
{ , , , , , , , , , , , , , , , , , , , },
{ , , , , , , , , , , , , , , , , , , , },
{ , , , , , , , , , , , , , , , , , , , },
{ , , , , , , , , , , , , , , , , , , , },
{ , , , , , , , , , , , , , , , , , , , },
{ , , , , , , , , , , , , , , , , , , , },
{ , , , , , , , , , , , , , , , , , , , }
};

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. UVA-11383 Golden Tiger Claw (KM算法)

    题目大意:一张可行二分图的权值以邻接矩阵的形式给了出来,现在要找每一个节点的可行顶标,使顶标和最小. 题目分析:直接用KM算法,结束后顶标之和最小...模板题. 代码如下: # include< ...

  2. html中用变量作为django字典的键值

    若字典为dic={'name': Barbie, 'age': 20},则在html中dic.name为Barbie,dic.age为20. 但若字典为dic={'Barbie': 1, 'Roger ...

  3. Integer与int的种种比较你知道多少

    如果面试官问Integer与int的区别:估计大多数人只会说道两点,Ingeter是int的包装类,int的初值为0,Ingeter的初值为null. 但是如果面试官再问一下Integer i = 1 ...

  4. restframework api(基础3CBV)

    一 CBV源码流程 urls.py from django.conf.urls import url from django.contrib import admin from app01 impor ...

  5. js中字符串处理成数字的方法

    <script> var a="11.1111"; var b="12.2222"; //第一种方法:乘以1的方法 //alert(a*1+b*1) ...

  6. Java——基本语法

    body, table{font-family: 微软雅黑; font-size: 10pt} table{border-collapse: collapse; border: solid gray; ...

  7. QT Creator快捷键不能用

    我现在搞明白了,热键之所以不行,是因为我开了Fakevim原因.关了fakevim就能用热键了. 如果开了Fakevim,连基本的Ctrl+C,这样的复制快捷键都不能用. 快速添加方法实体(.cpp) ...

  8. 如何从MTK机器的NVRAM中获取WIFI mac地址

    在MTK的机器中,如果不用特定的工具烧写MAC地址,在开机后打开WIFI后会显示: "NVRAM WARNING: Err=0x10" 这就是没有烧写mac地址的原因,所以每次打开 ...

  9. Ubuntu下gcc的简单使用

    一直不怎么用gcc,今天看了大神们的笔试题,不得不动手开始写程序了,差距那个大啊. gcc是ubuntu下的终端编译器,可以用来写C.C++的程序,简单用法如下: vim name1.c 先用vim打 ...

  10. 每天一个linux命令(网络):【转载】ifconfig命令

    许多windows非常熟悉ipconfig命令行工具,它被用来获取网络接口配置信息并对此进行修改.Linux系统拥有一个类似的工具,也就是ifconfig(interfaces config).通常需 ...