這個題目,用搜索做是很正常的想法 ,於是我就這樣交代碼了;
由於題給測試數據不大,200ms還是過了。
時間複雜度:
const int dx[] = {-1,0,1,0};
const int dy[] = {0,1,0,-1};
class Solution {
public:
int n,t;
bool vis[51][51];
int swimInWater(vector<vector<int>>& grid) {
n=grid.size();
for(t=0;t<n*n;t++){
if(grid[0][0]<=t){
memset(vis,0,sizeof(vis)); //每次dfs,都要刷新一下
if(dfs(0,0,grid)){
return t;
}
}
}
return n*n-1;
}
bool dfs(int x,int y,vector<vector<int>>& grid){
// cout<<x<<" "<<y<<endl;
if(x==n-1 && y==n-1){
return true;
}
vis[x][y] = 1;
for(int k=0;k<4;k++){
int nx = x + dx[k];
int ny = y + dy[k];
if(nx>=0&&ny>=0&&nx<n&&ny<n && grid[nx][ny]<=t && !vis[nx][ny]){
if(dfs(nx,ny,grid)){
return true;
}
// vis[nx,ny] = 0;這個地方不需要也不能還原現場,否則會冗餘搜索。
}
}
return false;
}
};
然後是怎麼想到二分的呢?dfs()
是一個關於時間t的函數,返回true 或false,相當於是在[1,n*n-1]這個區間猜一個數,剛好處於一個臨界點(超過這個臨界點都是true,不到臨界點都是false)。
這不就是一個二分應用裏面的一個猜大小數字的小遊戲嗎?
時間複雜度
const int dx[] = {-1,0,1,0};
const int dy[] = {0,1,0,-1};
class Solution {
public:
int n;
bool vis[51][51];
int swimInWater(vector<vector<int>>& grid) {
n=grid.size();
int l = grid[0][0], r = n*n-1,mid;
while(l<r){
int mid = (l+r)/2;
memset(vis,0,sizeof(vis));
if(dfs(0,0,mid,grid)){
r = mid;
}else{
l = mid +1;
}
}
return l;
}
bool dfs(int x,int y,int t,vector<vector<int>>& grid){
if(x==n-1 && y==n-1){
return true;
}
vis[x][y] = 1;
for(int k=0;k<4;k++){
int nx = x + dx[k];
int ny = y + dy[k];
if(nx>=0&&ny>=0&&nx<n&&ny<n && grid[nx][ny]<=t && !vis[nx][ny]){
if(dfs(nx,ny,t,grid)){
return true;
}
// vis[nx][ny] = 0;
}
}
return false;
}
};
這裏,我也用並查集做了一下,原理是一樣的。
const int dx[] = {-1,0,1,0};
const int dy[] = {0,1,0,-1};
struct UFS{
int f[50*50+10];
UFS(){
for(int i=0;i<50*50+10;i++){
f[i]=i;
}
}
int find(int x){
return x==f[x]?x:f[x]=find(f[x]);
}
void merge(int x,int y){
f[find(x)] = find(y);
}
};
class Solution {
public:
int swimInWater(vector<vector<int>>& grid) {
int n = grid.size(),t;
int l= grid[0][0],r=n*n-1;
while(l<r){
int mid = (l+r)/2;
UFS ufs;
for(int x=0;x<n;x++){
for(int y=0;y<n;y++){
if(grid[x][y]>mid){
continue;
}
for(int k=0;k<4;k++){
int nx = x + dx[k];
int ny = y + dy[k];
if(nx>=0 && ny>=0 && nx<n && ny<n && grid[nx][ny]<=mid){
ufs.merge(x*50+y,nx*50+ny);
}
}
}
}
if(ufs.find(0)==ufs.find((n-1)*50+(n-1))){
r = mid;
}else{
l = mid+1;
}
}
return l;
}
};
這題還有用優先隊列做的,暫時先擱着吧。
以後再補。