[BZOJ1052][HAOI2007]覆盖问题 二分+贪心

1052: [HAOI2007]覆盖问题

Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 2053  Solved: 959 [Submit][Status][Discuss]

Description

  某人在山上种了N棵小树苗。冬天来了,温度急速下降,小树苗脆弱得不堪一击,于是树主人想用一些塑料薄
膜把这些小树遮盖起来,经过一番长久的思考,他决定用3个L*L的正方形塑料薄膜将小树遮起来。我们不妨将山建
立一个平面直角坐标系,设第i棵小树的坐标为(Xi,Yi),3个L*L的正方形的边要求平行与坐标轴,一个点如果在
正方形的边界上,也算作被覆盖。当然,我们希望塑料薄膜面积越小越好,即求L最小值。

Input

  第一行有一个正整数N,表示有多少棵树。接下来有N行,第i+1行有2个整数Xi,Yi,表示第i棵树的坐标,保证
不会有2个树的坐标相同。

Output

  一行,输出最小的L值。

Sample Input

4
0 1
0 -1
1 0
-1 0

Sample Output

1

HINT

100%的数据,N<=20000

用一个最小矩形框住所有点,L*L的矩形一定放在4角之一。

枚举第一个放的位置,去掉已覆盖的,从新画最小矩形。

再枚举第二个放的位置,去掉后判断剩下的点能否用一个L*L的矩形覆盖。

二分L。

 #include<iostream>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
using namespace std;
int n;
struct data {
int x,y;
}a[];
int vis[];
int x1=,y1=,x2=-,y2=-;
void cut(int x,int y,int l) {
for(int i=;i<=n;i++) if(a[i].x<=x+l&&a[i].x>=x&&a[i].y<=y+l&&a[i].y>=y) vis[i]=;
}
void solve(int f,int l) {
if(f==) {
int x=,y=;
for(int i=;i<=n;i++) {
if(vis[i]) continue;
x=min(x,a[i].x);y=min(y,a[i].y);
}
cut(x,y,l);
}
if(f==) {
int x=,y=-;
for(int i=;i<=n;i++) {
if(vis[i]) continue;
x=min(x,a[i].x);y=max(y,a[i].y);
}
cut(x,y-l,l);
}
if(f==) {
int x=-,y=-;
for(int i=;i<=n;i++) {
if(vis[i]) continue;
x=max(x,a[i].x);y=max(y,a[i].y);
}
cut(x-l,y-l,l);
}
if(f==) {
int x=-,y=;
for(int i=;i<=n;i++) {
if(vis[i]) continue;
x=max(x,a[i].x);y=min(y,a[i].y);
}
cut(x-l,y,l);
}
}
bool check(int l) {
for(int i=;i<=;i++) {
for(int j=;j<=;j++) {
memset(vis,,sizeof(vis));
solve(i,l);solve(j,l);
int xx1=,yy1=,xx2=-,yy2=-;
for(int i=;i<=n;i++) {
if(vis[i])continue;
xx1=min(xx1,a[i].x);xx2=max(xx2,a[i].x);
yy1=min(yy1,a[i].y);yy2=max(yy2,a[i].y);
}
if(xx2-l<=xx1&&yy2-l<=yy1) return ;
}
}
return ;
}
int main() {
scanf("%d",&n);
for(int i=;i<=n;i++) scanf("%d%d",&a[i].x,&a[i].y);
int l=,r=;
while(l<=r) {
int mid=(l+r)>>;
if(check(mid)) r=mid-;
else l=mid+;
}
printf("%d",l);
}
上一篇:DSCP 与IP 优先级IP优先级


下一篇:【BZOJ 1052】 1052: [HAOI2007]覆盖问题 (乱搞)