题目链接:http://acm.nyist.edu.cn/JudgeOnline/problem.php?pid=306
这道题题意不难看懂,让我们求最小的一个路径的差值,这道题和之前写过的一道题很类似(我觉得一摸两样),用的是bfs+二分想看的可以看一下:传送门。这道题我用的是深搜,首先我们需要求出地图中的最大值和最小值,然后在最小值和最大值减去最小值这两个值里去二分差值(有点绕,仔细想一下就好),然后我们去判断这个差值能不能从左上角走到右下角,如果可以的话,我们再减小那个差值,大概思路就是这样,但是实现的时候会有好多细节问题需要去注意,细心一点就好了。需要注意的点是,地图的初始化都设为-1(不知道为什么不初始化就会wa),还有需要单独判断起点和终点是否符合那个差值。
AC代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#define maxn 105
using namespace std;
int MAP[maxn][maxn];
int vis[maxn][maxn];
int dir[4][2] = {1,0,0,1,-1,0,0,-1};
int n,Max,Min,flag;
void dfs(int L,int R,int x,int y){
if(flag)return ;
if(x == n-1 && y == n-1){
flag = 1;
return ;
}
for(int i=0;i<4;i++){
int X = x + dir[i][0];
int Y = y + dir[i][1];
if(MAP[X][Y] >= L && MAP[X][Y] <= R && vis[X][Y] == 0){
vis[X][Y] = 1;
dfs(L,R,X,Y);
}
}
}
bool Check(int x){
for(int i=Min;i<=Max-x;i++){
if(MAP[0][0] < i || MAP[0][0] > i + x) continue;
if(MAP[n-1][n-1] < i || MAP[n-1][n-1] > i + x) continue;
flag = 0;
memset(vis,0,sizeof(vis));
vis[0][0] = 1;
dfs(i,i+x,0,0);
if(flag)return true;
}
return false;
}
int main()
{
while(~scanf("%d",&n)){
Max = -1;
Min = 0x3f3f3f3f;
memset(MAP,-1,sizeof(MAP));
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
scanf("%d",&MAP[i][j]);
if(Max < MAP[i][j])Max = MAP[i][j];
if(Min > MAP[i][j])Min = MAP[i][j];
}
}
int l = 0, r = Max - Min , mid;
while(l < r){
mid = (l + r) >> 1;
if(Check(mid)){
r = mid;
}
else l = mid + 1;
}
printf("%d\n",r);
}
return 0;
}