洛谷P2658 汽车拉力比赛 题解 二分答案+搜索

题目链接:https://www.luogu.com.cn/problem/P2658

解题思路:

这道题当D确定的情况下,其实就是一个连通块问题。

然后我们二分答案求最小的D即可。

实现代码如下:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 550;
int n, m, h[maxn][maxn], flag[maxn][maxn], sx, sy;
bool vis[maxn][maxn];
int dir[4][2] = { -1, 0, 1, 0, 0, -1, 0, 1 };
inline bool inmap(int x, int y) {
    return x>=0 && x<n && y>=0 && y<m;
}
void find_sx_sy() {
    for (int i = 0; i < n; i ++)
        for (int j = 0; j < m; j ++)
            if (flag[i][j]) {
                sx = i; sy = j; return;
            }
}
void dfs(int x, int y, int D) {
    vis[x][y] = true;
    for (int i = 0; i < 4; i ++) {
        int xx = x + dir[i][0], yy = y + dir[i][1];
        if (inmap(xx, yy) && !vis[xx][yy] && abs(h[x][y]-h[xx][yy]) <= D)
            dfs(xx, yy, D);
    }
}
bool in_check() {
    for (int i = 0; i < n; i ++) for (int j = 0; j < m; j ++)
        if (flag[i][j] && !vis[i][j]) return false;
    return true;
}
bool check(int D) {
    memset(vis, 0, sizeof(vis));
    dfs(sx, sy, D);
    return in_check();
}
int main() {
    cin >> n >> m;
    for (int i = 0; i < n; i ++) for (int j = 0; j < m; j ++) cin >> h[i][j];
    for (int i = 0; i < n; i ++) for (int j = 0; j < m; j ++) cin >> flag[i][j];
    find_sx_sy();
    int L = 0, R = 1000000000, res;
    while (L <= R) {
        int mid = (L + R) / 2;
        if (check(mid)) res = mid, R = mid-1;
        else L = mid+1;
    }
    cout << res << endl;
    return 0;
}

洛谷P3073 和这题一样。

posted @ 2020-02-22 11:27  quanjun  阅读(170)  评论(0编辑  收藏  举报