洛谷 P2658 汽车拉力比赛

题目描述

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

赛场凹凸不平,所以被描述为 N∗MN∗M 的网格来表示海拔高度 (1≤M,N≤500)(1≤M,N≤500),每个单元格的海拔范围在 00 到 109109 之间。

其中一些单元格被定义为路标。组织者希望给整个路线指定一个难度系数 DD,这样参赛选手从任一路标到达别的路标所经过的路径上相邻单元格的海拔高度差不会大于 DD 。也就是说这个难度系数 DD 指的是保证所有路标相互可达的最小值。任一单元格和其东西南北四个方向上的单元格都是相邻的。

输入格式

第 11 行两个整数 MM 和 NN。第 22 行到第 M+1M+1 行,每行 NN 个整数描述海拔高度。第 2+M2+M 行到第 1+2M1+2M

行,每行 NN 个整数,每个数非 00 即 11,11 表示该单元格是一个路标。

输出格式

一个整数,即赛道的难度系数 DD。

输入输出样例

输入 #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

源码

#include <iostream>
#define MAXSIZE 501
#include <utility>
#include <cstring>
using namespace std;

typedef pair<int,int> PII;
PII q[MAXSIZE*MAXSIZE];
int m,n;
int high[MAXSIZE][MAXSIZE];
int flag[MAXSIZE][MAXSIZE];
int flag_num=0;
int x1,y1;
int dx[]={-1,0,1,0};
int dy[]={0,1,0,-1};
int st[MAXSIZE][MAXSIZE];

int check(int mid){
    int hh=0,tt=-1;
    int flag_cnt=1;
    st[x1][y1]=1;
    q[++tt]={x1,y1};
    while(hh<=tt){
        auto t=q[hh++];
        for(int i=0;i<4;i++){
            int a=t.first+dx[i];
            int b=t.second+dy[i];
            if(st[a][b]) continue;
            if(a<1 || a>m || b<1 || b>n) continue;
            if(abs(high[t.first][t.second]-high[a][b])>mid) continue;
            q[++tt]={a,b};
            st[a][b]=1;
            if(flag[a][b]==1){
                flag_cnt++;
                if(flag_cnt==flag_num){
                    return 1;
                }
            }
        }
    }
    return 0;
}
int main(){
    scanf("%d %d",&m,&n);
    for(int i=1;i<=m;i++){
        for(int j=1;j<=n;j++){
            scanf("%d",&high[i][j]);
        }
    }
    for(int i=1;i<=m;i++){
        for(int j=1;j<=n;j++){
            scanf("%d",&flag[i][j]);
            if(flag[i][j]==1) flag_num++;
        }
    }
    for(int i=1;i<=m;i++){
        for(int j=1;j<=n;j++){
            if(flag[i][j]==1){
                x1=i,y1=j;
                break;
            }
        }
    }
    int l=-1,r=1e9+1;
    while(l+1<r){
        memset(q,0,sizeof(q));
        memset(st,0,sizeof(st));
        int mid=(l+r)/2;
        if(check(mid)) r=mid;
        else l=mid;
    }
    if(check(l)) printf("%d",l);
    else 
    printf("%d\n",r);
    return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值