洛谷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。

輸入輸出樣例

輸入樣例

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

輸出樣例

21

一年前的比賽題qwq,答案單調性顯然,然而當時打了個bfs建圖+spfa過了,現在交上去神tmT一個點,於是擼了個二分+bfs。
代碼如下

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define ll long long
using namespace std;
const int sz = 501 * 501;
int map[501][501];
bool is[501][501];
int step[4][2] = {{1,0},{-1,0},{0,1},{0,-1}};
bool use[501][501];
struct point
{
    int x,y;
}start_point[sz];
int len;
queue < point > q;
int m,n;
void init()
{
    memset(use,0,sizeof(use));
}
void start_work()
{
    scanf("%d%d",&m,&n);
    for(int i = 1 ; i <= m ; i ++)
        for(int j = 1 ; j <= n ; j ++)
            scanf("%d",&map[i][j]);
    for(int i = 1 ; i <= m ; i ++)
        for(int j = 1 ; j <= n ; j ++)
        {
            scanf("%d",&is[i][j]);
            if(is[i][j])
                start_point[++len].x = i , start_point[len].y = j;
        }
}
void bfs(point s,ll k)
{
    use[s.x][s.y] = 1;
    q.push(s);
    while(!q.empty())
    {
        point f = q.front();
        q.pop();
        for(int i = 0 ; i < 4 ; i ++)
        {
            int nx = f.x + step[i][0];
            int ny = f.y + step[i][1];
            if(nx >= 1 && nx <= m && ny >= 1 && ny <= n && !use[nx][ny] && abs(map[f.x][f.y] - map[nx][ny]) <= k)
            {
                use[nx][ny] = 1;
                point nxt;
                nxt.x = nx;
                nxt.y = ny;
                q.push(nxt);
            }
        }
    }
}
bool check(ll mid)
{
    init();
    bfs(start_point[1],mid);
    for(int i = 1 ; i <= len ; i ++)
        if(!use[start_point[i].x][start_point[i].y])
            return false;
    return true;
}
ll work_ef()
{
    ll l = 0 , r = 214748364711ll;
    while(r - l > 1)
    {
        ll mid = (l + r) / 2;
        if(check(mid))
            r = mid;
        else
            l = mid;
    }
    if(check(l))
        return l;
    return r;
}
int main()
{
    start_work();
    printf("%lld\n",work_ef());
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章