題目鏈接
http://acm.nyist.net/JudgeOnline/problem.php?pid=306
http://acm.hznu.edu.cn/JudgeOnline/problem.php?id=1852
思路
參考:http://www.cnblogs.com/algorithms/archive/2012/07/10/2584420.html
比賽時這道沒有寫出來,思路是dfs+二分,這種類型的題這是第二次遇到了,看來這種思路適用性還是挺廣的。
就是二分遍歷難度差mid,然後判斷這個難度差限制下能否走到終點,如果可以的話大於mid的都可以,right=mid,否則就left=mid+1。
然後我一開始寫傻傻的按一般dfs的寫法,把vis還原了,直接導致超時,因爲這題完全可以不還原的,不符合條件的格子肯定不會走第二遍。
AC代碼
#include <bits/stdc++.h>
using namespace std;
int g[110][110];
int n;
int dx[]={1,-1,0,0};
int dy[]={0,0,-1,1};
int vis[110][110]={0};
bool success=0;
void dfs(int x,int y,int l,int r)
{
if(success)return;
if(g[x][y]>r || g[x][y]<l)return;
if(x==n && y==n)
{
success=1;
return;
}
for(int d=0 ; d<4 ; ++d)
{
int nx=x+dx[d],ny=y+dy[d];
if(nx>=1 && nx<=n && ny>=1 && ny<=n && !vis[nx][ny])
{
vis[x][y]=1;
dfs(nx,ny,l,r);
//vis[x][y]=0;
}
}
}
int big=0,small=9999;
bool judge(int dis)
{
success=false;
for(int i=small ; i+dis<=big ; ++i)
{
memset(vis,0,sizeof vis);
int l=i,r=i+dis;
vis[1][1]=1;
dfs(1,1,l,r);
if(success)return true;
}
return false;
}
int main()
{
scanf("%d",&n);
for(int i=1 ; i<=n ; ++i)
{
for(int j=1 ; j<=n ; ++j)
{
scanf("%d",&g[i][j]);
big=max(big,g[i][j]);
small=min(small,g[i][j]);
}
}
int left=0,right=big-small;
while(left<right)
{
int mid=(left+right)/2;
if(judge(mid))right=mid;
else left=mid+1;
}
printf("%d\n",left);
return 0;
}