题目链接
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;
}