题目链接:http://nyoj.top/web/contest/problem/cid/8/num/D
题目:
从左上走到右下,要求路径上的最大值与最小值的差值最小,输出最小值。
题解:
BFS+二分。
二分枚举插值,确定最小值,这样最大值也确定了。之后判断条件。
#include<bits/stdc++.h>
using namespace std;
typedef pair<int ,int> P;
const int maxn=105;
int a[maxn][maxn];
int vis[maxn][maxn];
int nx[4]={0,0,1,-1};
int ny[4]={1,-1,0,0};
int MAX,MIN,n;
int bfs()
{
queue<P> q;
q.push(P(1,1));
while(!q.empty())
{
P p=q.front();
q.pop();
if(vis[p.first][p.second]==1||(a[p.first][p.second]>MAX||a[p.first][p.second]<MIN)) continue;
vis[p.first][p.second]=1;
if(p.first==n&&p.second==n) return 1;
for(int i=0;i<4;i++)
{
int xx=nx[i]+p.first;
int yy=ny[i]+p.second;
if(a[xx][yy]<=MAX&&a[xx][yy]>=MIN&&vis[xx][yy]==0&&xx <= n && xx >= 1 && yy <= n && yy >= 1)
{
q.push(P(xx,yy));
}
}
}
return 0;
}
int f(int mid)
{
for(int i=0;i+mid<=120;i++)
{
memset(vis,0,sizeof(vis));
MIN=i;
MAX=i+mid;
if(bfs()) return 1;
}
return 0;
}
int main()
{
while(cin>>n)
{
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
scanf("%d",&a[i][j]);
int l=0,r=120;
while(l<r)
{
int mid=(l+r)/2;
if(f(mid))
r=mid;
else
l=mid+1;
}
cout<<l<<endl;
}
return 0;
}