P2658 汽车拉力比赛

汽车拉力比赛

题目描述

博艾市将要举行一场汽车拉力比赛。

赛场凹凸不平,所以被描述为 N ∗ M N*M NM 的网格来表示海拔高度 ( 1 ≤ M , N ≤ 500 ) (1 \leq M,N \leq 500) (1M,N500),每个单元格的海拔范围在 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;
}
  • 8
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值