汽车拉力比赛
题目描述
博艾市将要举行一场汽车拉力比赛。
赛场凹凸不平,所以被描述为 N ∗ M N*M N∗M 的网格来表示海拔高度 ( 1 ≤ M , N ≤ 500 ) (1 \leq M,N \leq 500) (1≤M,N≤500),每个单元格的海拔范围在 0 0 0 到 1 0 9 10^9 109 之间。
其中一些单元格被定义为路标。组织者希望给整个路线指定一个难度系数 D D D,这样参赛选手从任一路标到达别的路标所经过的路径上相邻单元格的海拔高度差不会大于 D D D 。也就是说这个难度系数 D D D 指的是保证所有路标相互可达的最小值。任一单元格和其东西南北四个方向上的单元格都是相邻的。
输入格式
第 1 1 1 行两个整数 M M M 和 N N N。第 2 2 2 行到第 M + 1 M+1 M+1 行,每行 N N N 个整数描述海拔高度。第 2 + M 2+M 2+M 行到第 1 + 2 M 1+2M 1+2M
行,每行 N N N 个整数,每个数非 0 0 0 即 1 1 1, 1 1 1 表示该单元格是一个路标。
输出格式
一个整数,即赛道的难度系数 D D D。
样例 #1
样例输入 #1
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
样例输出 #1
21
code:
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
#define x first
#define y second
using namespace std;
typedef pair<int, int> PII;
const int N = 510;
int n, m;
int high[N][N];
int flag[N][N];
int cnt_flag = 0; //统计路标总数
queue<PII>q;
int x1 = 0, y12 = 0;
bool st[N][N];
int dx[] = {-1, 0, 1, 0};
int dy[] = {0, 1, 0, -1};
bool check(int mid) {
q.push({x1,y12});
st[x1][y12] = true;
int cnt = 1; //统计当前已到达的路标的个数
while(!q.empty()) {
auto t = q.front();
q.pop();
for(int i = 0; i < 4; i ++) {
int a = t.x + dx[i], b = t.y + dy[i];
if(a < 1 || a > n || b < 1 || b > m) continue;
if(st[a][b]) continue;
if(abs(high[t.x][t.y] - high[a][b]) > mid) continue;
q.push({a,b});
st[a][b] = true;
if(flag[a][b] == 1) {
cnt ++;
}
}
}
if(cnt == cnt_flag) {
return true;
}
return false;
}
int main() {
scanf("%d %d", &n, &m);
for(int i = 1; i <= n; i ++) {
for(int j = 1; j <= m; j ++) {
scanf("%d", &high[i][j]);
}
}
for(int i = 1; i <= n; i ++) {
for(int j = 1; j <= m; j ++) {
scanf("%d", &flag[i][j]);
if(flag[i][j] == 1) {
cnt_flag ++;
}
}
}
for(int i = 1; i <= n; i ++) {
for(int j = 1; j <= m; j ++) {
if(flag[i][j] == 1) {
x1 = i, y12 = j;
break;
}
}
}
int l = -1, r = 1e9 + 10;
while(l + 1 < r) {
int mid = (l + r) / 2;
memset(st, false, sizeof st);
if(check(mid)) {
r = mid;
}
else l = mid;
}
printf("%d\n", r);
return 0;
}