Honeymoon Hike
题目链接;
参考博客
https://blog.csdn.net/u013480600/article/details/26097213
解题思路
这道题主要使用了搜索,二分,枚举算法,
对于搜索:DFS的时间复杂度为O(V+E),V <= 10000 ,E <= 40000;
对于二分:时间复杂度 为 lg(n); n<=200;
对于枚举:时间复杂度为 :O(n); n <= 200;
所以总体的计算量上限为 :8 * 200 * 50000 = 8 * 10^7;
题目要求的时间限制为:5s;大约的计算量为5 * 10^7;
基本满足题目要求;
实现1:非递归版DFS + 二分 + 枚举
这里出现了超时
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <stack>
#include <vector>
#include <queue>
using namespace std;
int a[105][105];
int vis[105][105];
int n;
#define INF 0x7fffffff
struct Nod
{
int x;
int y;
Nod(){
}
};
int x[4]={-1,1,0,0};
int y[4]={0,0,-1,1};
bool dfs(int si,int sj,int low,int high)
{
memset(vis,0,sizeof(vis));
stack<Nod>st;
Nod tmp;
tmp.x = si;
tmp.y = sj;
st.push(tmp);
vis[si][sj] = 1;
if(a[si][sj] < low || a[si][sj] > high) return false;
while(!st.empty())
{
Nod now = st.top();
int nowi = now.x;
int nowj = now.y;
if(nowi == n && nowj == n) return true;
int ni,nj;
bool noFind =true;
for(int i = 0; i < 4; ++i)
{
ni = nowi + x[i];
nj = nowj + y[i];
if(ni > 0 && ni <= n && nj > 0 && nj <= n)
{
if(!vis[ni][nj])
{
vis[ni][nj] = 1;
if(!(a[ni][nj] >= low && a[ni][nj] <= high)) continue;
tmp.x = ni;
tmp.y = nj;
st.push(tmp);
noFind = false;
break;
}
}
}
if(noFind)
st.pop();
}
return false;
}
bool check(int low,int high,int d)
{
int e = high - d;
for(int i = low; i <= e; ++i)
{
if(dfs(1, 1, i, i + d))
{
return true;
}
}
return false;
}
bool input(int order)
{
scanf("%d",&n);
int low = INF,high = -1;
for(int i = 1; i <= n; ++i)
{
for(int j = 1; j <= n; ++j)
{
scanf("%d",&a[i][j]);
if(a[i][j] < low)
{
low = a[i][j];
}else if(a[i][j] > high){
high = a[i][j];
}
}
}
int mid;
int max_d = high - low;
int L = 0;
int R = max_d + 1;
while(L < R)
{
mid = (L + R) >> 1;
if(check(low, high, mid))R = mid;
else L = mid + 1;
}
printf("Scenario #%d:
",order);
printf("%d
",R);
printf("
");
return true;
}
int main()
{
int T;
scanf("%d",&T);
for(int i = 1; i <= T; ++i)
{
input(i);
}
return 0;
}
实现二:递归DFS + 二分 + 枚举(通过)
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <stack>
#include <vector>
#include <queue>
using namespace std;
int a[105][105];
int vis[105][105];
int n;
#define INF 0x7fffffff
int x[4]={-1,1,0,0};
int y[4]={0,0,-1,1};
bool dfs(int si,int sj,int low,int high)
{
if(!(a[si][sj] >= low && a[si][sj] <= high)) return false;
if(si == n && sj == n) return true;
int nowi, nowj, ni, nj;
nowi = si;
nowj = sj;
for(int i = 0; i < 4; ++i)
{
ni = nowi + x[i];
nj = nowj + y[i];
if(ni > 0 && ni <= n && nj > 0 && nj <= n)
{
if(!vis[ni][nj])
{
vis[ni][nj] = 1;
if(dfs(ni,nj,low,high)) return true;
}
}
}
return false;
}
bool check(int low,int high,int d)
{
int e = high - d;
for(int i = low; i <= e; ++i)
{
memset(vis,0,sizeof(vis));
if(dfs(1, 1, i, i + d))
{
return true;
}
}
return false;
}
bool input(int order)
{
scanf("%d",&n);
int low = INF,high = -1;
for(int i = 1; i <= n; ++i)
{
for(int j = 1; j <= n; ++j)
{
scanf("%d",&a[i][j]);
if(a[i][j] < low)
{
low = a[i][j];
}else if(a[i][j] > high){
high = a[i][j];
}
}
}
int mid;
int max_d = high - low;
int L = 0;
int R = max_d + 1;
while(L < R)
{
mid = (L + R) >> 1;
if(check(low, high, mid))R = mid;
else L = mid + 1;
}
printf("Scenario #%d:
",order);
printf("%d
",R);
printf("
");
return true;
}
int main()
{
int T;
scanf("%d",&T);
for(int i = 1; i <= T; ++i)
{
input(i);
}
return 0;
}