P2658 汽车拉力比赛 题解

问题描述

题目描述

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

赛场凹凸不平,所以被描述为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。

输入输出样例

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

AC代码:

#include<bits/stdc++.h>
using namespace std;
bool c[509][509],flag=1,vis[509][509];
int n,m,a[509][509],l,r,mid,ans,st,en,tp;
int dx[5]={0,0,1,0,-1},dy[5]={0,1,0,-1,0};
bool bfs(){
    queue<int> x, y;
    int now=1;
    x.push (st), y.push (en);
    vis[st][en]=1;
    while(!x.empty()){
        int ux=x.front(),uy=y.front();
        if(now==tp) return true;
        x.pop();
        y.pop();
        for(int i=1;i<=4;i++) {
            int nx=ux+dx[i], ny=uy+dy[i];
            if(nx<1||nx>n||ny<1||ny>m||vis[nx][ny]) continue;
            int v=abs(a[nx][ny]-a[ux][uy]);
            if(v>mid) continue;
            else{ 
                if(c[nx][ny]) now++;
                x.push(nx);
                y.push(ny);
                vis[nx][ny]=1;
            } 
        }
    }
    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",&a[i][j]);
            r=max(r,a[i][j]);
        }
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            scanf("%d",&c[i][j]);
            if(c[i][j]) tp++; 
            if(flag&&c[i][j]){
                st=i;
                en=j;
                flag=0;
            }
        } 
    }
    while(l<=r){
        mid=l+r>>1; 
        memset(vis,false,sizeof(vis));
        if(bfs()){
            r=mid-1;
            ans=mid;
        }
        else l=mid+1;
    } 
    printf("%d",ans); 
    return 0;
}

原因分析:

题意理解需注意:(这样参赛选手从任一路标到达别的路标所经过的路径上相邻单元格的海拔高度差不会大于D。也就是说这个难度系数D指的是保证所有路标相互可达的最小值),找一条相邻单元格海拔最接近的路径中最大海拔差输出,只需BFS+二分优化即可

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值