知识点:二分,深度优先搜索
难度:4
这个题是最小化的二分,我们把求最优解问题转化为判定问题,那么就是当前拖拉机价钱能否走一半的地图,这里一半的地图就是把地图划分连通块,有没有连通块的个数达到一半,也就是起点是任意的,这个题目上面没有说,但是我看了题解里面的题意,就是这个意思,那么就很好做了,判定函数里面用了深搜来划分连通块,并且记录每个连通块里面的元素的个数,最后看看有没有哪个连通块元素的个数是超过一半的,写了17分钟过了
#include <bits/stdc++.h>
using namespace std;
const int N = 505;
int n, a[N][N], b[N][N], c[N * N], cnt;
void dfs(int x, int y, int z) {
b[x][y] = cnt;
c[cnt]++;
int dx[4] = {-1, 0, 1, 0};
int dy[4] = {0, 1, 0, -1};
for (int i = 0; i < 4; i++) {
int x1 = x + dx[i];
int y1 = y + dy[i];
if (x1 < 0 || x1 >= n || y1 < 0 || y1 >= n) continue;
if (b[x1][y1] || abs(a[x][y] - a[x1][y1]) > z) continue;
dfs(x1, y1, z);
}
}
bool check(int x) {
cnt = 0;
memset(b, 0, sizeof(b));
memset(c, 0, sizeof(c));
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (!b[i][j]) {
cnt++;
dfs(i, j, x);
}
}
}
for (int i = 1; i <= cnt; i++) {
if (c[i] >= n * n / 2) return true;
}
return false;
}
int main() {
cin >> n;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) cin >> a[i][j];
}
int l = 0, r = 1e6;
while (l < r) {
int mid = (l + r) >> 1;
if (check(mid)) r = mid;
else l = mid + 1;
}
cout << l;
return 0;
}