洛谷2658 汽车拉力比赛

洛谷2658 汽车拉力比赛

本题地址: http://www.luogu.org/problem/show?pid=2658

题目描述

博艾市将要举行一场汽车拉力比赛。
赛场凹凸不平,所以被描述为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

【思路】

  二分+BFS。

  二分D,BFS判断是否可以到达全部路标即可。

 

【代码】

 

 1 #include<iostream>
 2 #include<cstring>
 3 #include<queue>
 4 #include<cmath>
 5 #define FOR(a,b,c) for(int a=(b);a<=(c);a++)
 6 using namespace std;
 7 
 8 const int maxn = 500+10;
 9 const int INF=1e9;
10 const int dx[]={0,0,1,-1};
11 const int dy[]={1,-1,0,0};
12 struct Node{
13     int x,y;
14 };
15 int is_P[maxn][maxn];
16 int G[maxn][maxn];
17 int n,m,sx,sy,sum=0;
18 bool inside(int x,int y) {
19     return x>0 && x<=n && y>0 && y<=m;
20 }
21 bool can(int D) {
22     queue<Node> q;
23     bool vis[maxn][maxn];
24     memset(vis,0,sizeof(vis));
25     
26     int cnt=1;
27     vis[sx][sy]=1;
28     q.push((Node){sx,sy});
29     while(!q.empty()) {
30         Node u=q.front(); q.pop();
31         int x=u.x,y=u.y;
32         FOR(i,0,3) {
33             int xx=x+dx[i],yy=y+dy[i];
34             if(inside(xx,yy) && !vis[xx][yy] &&(abs(G[xx][yy]-G[x][y])<=D)) {
35                 vis[xx][yy]=1;
36                 cnt += is_P[xx][yy];
37                 if(cnt==sum) return true;
38                 q.push((Node){xx,yy});
39             }
40         }
41     }
42     return false;
43 }
44 
45 int main() {
46     ios::sync_with_stdio(false);
47     cin>>n>>m;
48     int _min=INF,_max=0;
49     FOR(i,1,n) FOR(j,1,m){
50         cin>>G[i][j];
51         _min=min(_min,G[i][j]);
52         _max=max(_max,G[i][j]);
53     }
54     FOR(i,1,n) FOR(j,1,m) {
55         cin>>is_P[i][j];
56         sum += is_P[i][j];
57         if(is_P[i][j]) sx=i,sy=j;   //从1开始 
58     }
59     int L=0,R=_max-_min+1;
60     while(L<R) {
61         int M=L+(R-L)/2;
62         if(can(M)) R=M;
63         else L=M+1;
64     }
65     cout<<L<<"\n";
66     return 0;
67 }

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值