[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。

 

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<cstdlib>
 5 #include<algorithm>
 6 using namespace std;
 7 int n;
 8 struct data {
 9     int x,y;
10 }a[20002];
11 int vis[20002];
12 int x1=2147483647,y1=2147483647,x2=-2147483640,y2=-2147483640;
13 void cut(int x,int y,int l) {
14     for(int i=1;i<=n;i++) if(a[i].x<=x+l&&a[i].x>=x&&a[i].y<=y+l&&a[i].y>=y) vis[i]=1;
15 }
16 void solve(int f,int l) {
17     if(f==1) {
18         int x=2147483647,y=2147483647;
19         for(int i=1;i<=n;i++) {
20             if(vis[i]) continue;
21             x=min(x,a[i].x);y=min(y,a[i].y);
22         }
23         cut(x,y,l);
24     }
25     if(f==2) {
26         int x=2147483647,y=-2147483640;
27         for(int i=1;i<=n;i++) {
28             if(vis[i]) continue;
29             x=min(x,a[i].x);y=max(y,a[i].y);
30         }
31         cut(x,y-l,l);
32     }
33     if(f==3) {
34         int x=-2147483640,y=-2147483640;
35         for(int i=1;i<=n;i++) {
36             if(vis[i]) continue;
37             x=max(x,a[i].x);y=max(y,a[i].y);
38         }
39         cut(x-l,y-l,l);
40     }
41     if(f==4) {
42         int x=-2147483647,y=2147483640;
43         for(int i=1;i<=n;i++) {
44             if(vis[i]) continue;
45             x=max(x,a[i].x);y=min(y,a[i].y);
46         }
47         cut(x-l,y,l);
48     }
49 }
50 bool check(int l) {
51     for(int i=1;i<=4;i++) {
52         for(int j=1;j<=4;j++) {
53             memset(vis,0,sizeof(vis));
54             solve(i,l);solve(j,l);
55             int xx1=2147483647,yy1=2147483647,xx2=-2147483640,yy2=-2147483640;
56             for(int i=1;i<=n;i++) {
57                 if(vis[i])continue;
58                 xx1=min(xx1,a[i].x);xx2=max(xx2,a[i].x);
59                 yy1=min(yy1,a[i].y);yy2=max(yy2,a[i].y);
60             }
61             if(xx2-l<=xx1&&yy2-l<=yy1) return 1;
62         }
63     }
64     return 0;
65 }
66 int main() {
67     scanf("%d",&n);
68     for(int i=1;i<=n;i++) scanf("%d%d",&a[i].x,&a[i].y);
69     int l=1,r=2147483640;
70     while(l<=r) {
71         int mid=(l+r)>>1;
72         if(check(mid)) r=mid-1;
73         else l=mid+1;
74     }
75     printf("%d",l);
76 }
View Code

 

 

 

posted @ 2017-10-17 20:36  wls001  阅读(89)  评论(0编辑  收藏