【BZOJ1052】[HAOI2007]覆盖问题
【BZOJ1052】[HAOI2007]覆盖问题
题面
题解
二分答案是显然的。
算一下包含所有的点的最小矩形的范围\((x1,y1)\)\((x2,y2)\)
贪心思考一下肯定是把塑料薄膜其中一个角放在此矩形上的
然后\(dfs\)判一下即可
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
inline int gi() {
register int data = 0, w = 1;
register char ch = 0;
while (!isdigit(ch) && ch != '-') ch = getchar();
if (ch == '-') w = -1, ch = getchar();
while (isdigit(ch)) data = 10 * data + ch - '0', ch = getchar();
return w * data;
}
void chkmax(int &x, int y) { if (x < y) x = y; }
void chkmin(int &x, int y) { if (x > y) x = y; }
const int MAX_N = 20005;
int N, vis[MAX_N];
pair<int, int> p[MAX_N];
#define x first
#define y second
void cover(int x1, int x2, int y1, int y2, int id) {
for (int i = 1; i <= N; i++)
if (!vis[i] && x1 <= p[i].x && p[i].x <= x2 && y1 <= p[i].y && p[i].y <= y2)
vis[i] = id;
}
void uncover(int id) { for (int i = 1; i <= N; i++) if (vis[i] == id) vis[i] = 0; }
bool dfs(int tot, int L) {
int _x[2], _y[2]; _x[0] = _y[0] = 2e9, _x[1] = _y[1] = -2e9;
for (int i = 1; i <= N; i++)
if (!vis[i])
chkmin(_x[0], p[i].x), chkmax(_x[1], p[i].x), chkmin(_y[0], p[i].y), chkmax(_y[1], p[i].y);
if (max(_x[1] - _x[0], _y[1] - _y[0]) <= L) return 1;
if (tot == 3) return 0;
for (int i = 0; i < 2; i++)
for (int j = 0; j < 2; j++) {
if (i == 0) {
if (j == 0) cover(_x[0], _x[0] + L, _y[0], _y[0] + L, tot);
else cover(_x[0], _x[0] + L, _y[1] - L, _y[1], tot);
} else {
if (j == 0) cover(_x[1] - L, _x[1], _y[0], _y[0] + L, tot);
else cover(_x[1] - L, _x[1], _y[1] - L, _y[1], tot);
}
if (dfs(tot + 1, L)) return 1;
uncover(tot);
}
return 0;
}
bool check(int L) {
memset(vis, 0, sizeof(vis));
return dfs(1, L);
}
int main () {
N = gi(); for (int i = 1; i <= N; i++) p[i].x = gi(), p[i].y = gi();
int l = 0, r = 2e9, ans = 2e9;
while (l <= r) {
int mid = ((long long)l + r) >> 1ll;
if (check(mid)) r = mid - 1, ans = mid;
else l = mid + 1;
}
printf("%d\n", ans);
return 0;
}