BZOJ1052 [HAOI2007]覆盖问题
1052: [HAOI2007]覆盖问题
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 2401 Solved: 1101
[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的长度,但是check合法性很麻烦。容易得出,如果用一个矩形包围所有点,那么长度为L的正方形的最优策略一定是位于矩形的四个角中的其中一个,枚举四个角,然后把位于小正方形内的点全部剔除,就变成了用两个小正方形覆盖所有点的子问题,于是用dfs直到第三层处理完后看是否涵盖所有点即可。
一开始tmp数组和cnt开成了全局变量,导致dfs过程中会不断覆盖之前的值...调了好久
1 #include <bits/stdc++.h> 2 using namespace std; 3 int n; 4 struct Node{ 5 int x,y; 6 }; 7 Node a[20050]; 8 int vis[20050]; 9 10 void cut(int minx,int miny,int maxx,int maxy,int &cnt,int tmp[]){ 11 for (int i = 0;i < n;++i){ 12 if (a[i].x >= minx && a[i].x <= maxx && a[i].y >= miny && a[i].y <= maxy) { 13 vis[i]++; 14 tmp[cnt++] = i; 15 } 16 } 17 } 18 19 bool check(int L,int step){ 20 if (step == 3) { 21 for (int i = 0;i < n;++i){ 22 if (!vis[i]) return false; 23 } 24 return true; 25 } 26 int minx,miny,maxx,maxy; 27 minx = miny = 1e9+7; 28 maxx = maxy = -1e9+7; 29 for (int i = 0;i < n;++i){ 30 if (vis[i]) continue; 31 minx = min(minx,a[i].x); 32 miny = min(miny,a[i].y); 33 maxx = max(maxx,a[i].x); 34 maxy = max(maxy,a[i].y); 35 } 36 37 int cnt = 0,tmp[20050]; 38 cut(minx,miny,minx+L,miny+L,cnt,tmp); 39 if (check(L,step+1)) return true; 40 for (int i = 0;i < cnt;++i){ 41 vis[tmp[i]]--; 42 } 43 44 cnt = 0; 45 cut(minx,maxy-L,minx+L,maxy,cnt,tmp); 46 if (check(L,step+1)) return true; 47 for (int i = 0;i < cnt;++i) vis[tmp[i]]--; 48 49 cnt = 0; 50 cut(maxx-L,maxy-L,maxx,maxy,cnt,tmp); 51 if (check(L,step+1)) return true; 52 for (int i = 0;i < cnt;++i) vis[tmp[i]]--; 53 54 cnt = 0; 55 cut(maxx-L,miny,maxx,miny+L,cnt,tmp); 56 if (check(L,step+1)) return true; 57 for (int i = 0;i < cnt;++i) vis[tmp[i]]--; 58 return false; 59 } 60 61 62 int main(){ 63 scanf("%d",&n); 64 for (int i = 0;i < n;++i){ 65 scanf("%d%d",&a[i].x,&a[i].y); 66 } 67 int l = 0; 68 int r = 1e9+7; 69 while(l < r){ 70 int mid = (l+r) >> 1; 71 memset(vis,0,sizeof(vis)); 72 if (check(mid,0)) r = mid; 73 else l = mid+1; 74 } 75 printf("%d\n",l); 76 return 0; 77 }