洛谷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 和这题一样。