[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
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 }
O(∩_∩)O~ (*^__^*) 嘻嘻…… O(∩_∩)O哈哈~