1.方法一:利用优先队列(最小堆),和并查集。
思路:时间从0 处开始,每一个时间点,利用最小堆搜索刚好溢满的网格点,然后遍历,并且合并(后搜索的向先搜索的合并)。当第一个节点与终点合并完后,即找到了最短时间。
#include<iostream>
class Solution {
public:
struct node{
int x,y,h;
node(int _x,int _y,int _h):x(_x),y(_y),h(_h){}
bool operator<(const node& other) const{
return this->h>other.h;
}
};
vector<int> f;
int fat(int x){
if(f[x]!=x){
f[x]=fat(f[x]);
}
return f[x];
}
int swimInWater(vector<vector<int>>& grid) {
vector<int> dr={-1,1,0,0};
vector<int> dc={0,0,-1,1};
int n=grid.size(),m=grid[0].size();
priority_queue<node> nodes;
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
f.push_back(i*n+j);
nodes.push(node(i,j,grid[i][j]));
}
}
cout<<f[0]<<" "<<f[n*n-1]<<endl;
for(int t=0;t<n*n;t++){
while(!nodes.empty()&&nodes.top().h==t){
auto tp=nodes.top();
nodes.pop();
for(int i=0;i<4;i++){
int nx=tp.x+dr[i];
int ny=tp.y+dc[i];
int nz=nx*n+ny;
if(nx>=0&&nx<n&&ny>=0&&ny<n&&grid[nx][ny]<=t){
f[fat(nz)]=fat(tp.x*n+tp.y);
}
}
}
if(fat(0)==fat(n*n-1)) return t;
}
return n*n-1;
}
};
2.方法二:二分查找,如果不行,代表最短时间至少要再加一。如果可以则先暂时停在 mid处。根据下一步判断结果,找出最短时间。如此迭代下去。
class Solution {
public:
int swimInWater(vector<vector<int>>& grid) {
int n=grid.size();
int lt=0,rt=n*n;
while(lt<rt){
int mid=(lt+rt-1)/2;
if(!ispossible(mid,grid)){
lt=mid+1;
}else rt=mid;
}
return lt;
}
bool ispossible(int t,vector<vector<int>>& grid){
int n=grid.size();
vector<int> dr={-1,1,0,0}, dc={0,0,-1,1},vis(n*n,0);
queue<int> qu;
if(grid[0][0]<=t){
qu.push(0);
vis[0]=1;
}
while(!qu.empty()){
int tp=qu.front();
qu.pop();
for(int i=0;i<4;i++){
int nx=tp/n+dr[i];
int ny=tp%n+dc[i];
if(nx>=0&&nx<n&&ny>=0&&ny<n&&grid[nx][ny]<=t&&vis[nx*n+ny]==0){
if(nx==n-1&&ny==n-1) return true;
qu.push(nx*n+ny);
vis[nx*n+ny]=1;
}
}
}
return false;
}
};
前两个方法都是先确定时间,再判断是否有可行的路径。
3.方法三:通过找高度最低的路径直接来寻找时间。
最小堆,BFS遍历。
class Solution {
public:
struct node{
int x,y,h;
};
int sosu(vector<node>& nodes,int N){
int x=INT_MAX,y;
for(node x2:nodes){
if(!vis[x2.y*N+x2.x]){
if(x>x2.h){
x=x2.h;
y=x2.y*N+x2.x;
}
}
}
return y;
}
vector<int> vis;
int ans=-1;
int swimInWater(vector<vector<int>>& grid) {
int N=grid.size();
vis.resize(N*N);
for(int i=0;i<N*N;i++)
vis[i]=0;
vector<node> nodes;
node tmp;
tmp.x=0;
tmp.y=0;
tmp.h=grid[tmp.y][tmp.x];
nodes.push_back(tmp);
//vis[tmp.y*(N)+tmp.x]=1;
vector<int> dx={1,-1,0,0};
vector<int> dy={0,0,1,-1};
while(1){
int q=sosu(nodes,N);
int x=q%(N),y=q/(N);
ans=max(ans,grid[y][x]);
vis[y*(N)+x]=1;
if(x==N-1&&y==N-1)
return ans;
for(int i=0;i<4;i++){
int nx=x+dx[i],ny=y+dy[i];
if(nx>=0&&nx<=N-1&&ny>=0&&ny<=N-1&&vis[ny*N+nx]==0){
node tmp1;
tmp1.x=nx;
tmp1.y=ny;
tmp1.h=grid[ny][nx];
nodes.push_back(tmp1);
}
}
}
}
};