题目描述
博艾市将要举行一场汽车拉力比赛。
赛场凹凸不平,所以被描述为M*N的网格来表示海拔高度(1≤ M,N≤500),每个单元格的海拔范围在0到10^9之间。
其中一些单元格被定义为路标。组织者希望给整个路线指定一个难度系数D,这样参赛选手从任一路标到达别的路标所经过的路径上相邻单元格的海拔高度差不会大于D。也就是说这个难度系数D指的是保证所有路标相互可达的最小值。任一单元格和其东西南北四个方向上的单元格都是相邻的。
输入输出格式
输入格式:
第一行两个整数M和N。第2行到第M+1行,每行N个整数描述海拔高度。第2+M行到第1+2M
行,每行N个整数,每个数非0即1,1表示该单元格是一个路标。
输出格式:
一个整数,即赛道的难度系数D。
输入输出样例
输入样例
3 5
20 21 18 99 5
19 22 20 16 26
18 17 40 60 80
1 0 0 0 1
0 0 0 0 0
0 0 0 0 1
输出样例
21
一年前的比赛题qwq,答案单调性显然,然而当时打了个bfs建图+spfa过了,现在交上去神tmT一个点,于是撸了个二分+bfs。
代码如下
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define ll long long
using namespace std;
const int sz = 501 * 501;
int map[501][501];
bool is[501][501];
int step[4][2] = {{1,0},{-1,0},{0,1},{0,-1}};
bool use[501][501];
struct point
{
int x,y;
}start_point[sz];
int len;
queue < point > q;
int m,n;
void init()
{
memset(use,0,sizeof(use));
}
void start_work()
{
scanf("%d%d",&m,&n);
for(int i = 1 ; i <= m ; i ++)
for(int j = 1 ; j <= n ; j ++)
scanf("%d",&map[i][j]);
for(int i = 1 ; i <= m ; i ++)
for(int j = 1 ; j <= n ; j ++)
{
scanf("%d",&is[i][j]);
if(is[i][j])
start_point[++len].x = i , start_point[len].y = j;
}
}
void bfs(point s,ll k)
{
use[s.x][s.y] = 1;
q.push(s);
while(!q.empty())
{
point f = q.front();
q.pop();
for(int i = 0 ; i < 4 ; i ++)
{
int nx = f.x + step[i][0];
int ny = f.y + step[i][1];
if(nx >= 1 && nx <= m && ny >= 1 && ny <= n && !use[nx][ny] && abs(map[f.x][f.y] - map[nx][ny]) <= k)
{
use[nx][ny] = 1;
point nxt;
nxt.x = nx;
nxt.y = ny;
q.push(nxt);
}
}
}
}
bool check(ll mid)
{
init();
bfs(start_point[1],mid);
for(int i = 1 ; i <= len ; i ++)
if(!use[start_point[i].x][start_point[i].y])
return false;
return true;
}
ll work_ef()
{
ll l = 0 , r = 214748364711ll;
while(r - l > 1)
{
ll mid = (l + r) / 2;
if(check(mid))
r = mid;
else
l = mid;
}
if(check(l))
return l;
return r;
}
int main()
{
start_work();
printf("%lld\n",work_ef());
return 0;
}