bzoj1052 9.20考试 第二题 覆盖问题
1052: [HAOI2007]覆盖问题
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 2004 Solved: 937
[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
这道题当时一看还以为是一道几何题,就先放着最后打然后就华丽丽的爆零了。
最后正解并不是我当初第一反应的几何,但确实是我当时第二反应——二分答案,exciting……
我们可以通过一个无法用语言描述的证明可知至少有一个正方形是位于最小矩形的一个角上的。因为一共就三个正方形,所以我们dfs每个正方形位于当前最小矩形的四个角的情况就好了,那么时间复杂度就是O(log (2*10^9)*n*64)轻松搞掉。
1 #include<iostream> 2 #include<cstdlib> 3 #include<cstdio> 4 #include<cstring> 5 #include<queue> 6 #include<algorithm> 7 #include<cmath> 8 #include<map> 9 #include<vector> 10 #define N 20005 11 using namespace std; 12 int n,xx,nx,xy,ny; 13 bool fw[N]; 14 struct no 15 { 16 int x,y; 17 }node[N]; 18 bool dfs(long long L,int x,int sum) 19 { 20 if(sum==n)return 1; 21 if(x==4) 22 return 0; 23 int xxx=-0x7fffffff,nnx=0x7fffffff,xxy=-0x7fffffff,nny=0x7fffffff; 24 if(x==1) 25 xxx=xx,nnx=nx,xxy=xy,nny=ny; 26 else 27 { 28 for(int i=1;i<=n;i++) 29 { 30 if(fw[i])continue; 31 if(node[i].x>xxx) xxx=node[i].x; 32 if(node[i].x<nnx) nnx=node[i].x; 33 if(node[i].y>xxy) xxy=node[i].y; 34 if(node[i].y<nny) nny=node[i].y; 35 } 36 } 37 bool b[N]; 38 int t=sum; 39 memcpy(b,fw,sizeof(fw)); 40 for(int i=1;i<=n;i++) 41 { 42 if(!fw[i]&&node[i].x<=nnx+L&&node[i].y<=nny+L) 43 fw[i]=1,t++; 44 } 45 if(dfs(L,x+1,t)) return 1; 46 memcpy(fw,b,sizeof(b)); 47 t=sum; 48 for(int i=1;i<=n;i++) 49 { 50 if(!fw[i]&&node[i].x<=nnx+L&&node[i].y>=xxy-L) 51 fw[i]=1,t++; 52 } 53 if(dfs(L,x+1,t)) return 1; 54 55 memcpy(fw,b,sizeof(b)); 56 t=sum; 57 for(int i=1;i<=n;i++) 58 { 59 if(!fw[i]&&node[i].x>=xxx-L&&node[i].y<=nny+L) 60 fw[i]=1,t++; 61 } 62 if(dfs(L,x+1,t)) return 1; 63 64 t=sum; 65 memcpy(fw,b,sizeof(b)); 66 for(int i=1;i<=n;i++) 67 { 68 if(!fw[i]&&node[i].x>=xxx-L&&node[i].y>=xxy-L) 69 fw[i]=1,t++; 70 } 71 if(dfs(L,x+1,t)) return 1; 72 memcpy(fw,b,sizeof(b)); 73 return 0; 74 } 75 int main() 76 { 77 scanf("%d",&n); 78 xx=-0x7fffffff,nx=0x7fffffff,ny=0x7fffffff,xy=-0x7fffffff; 79 for(int i=1;i<=n;i++) 80 { 81 scanf("%d%d",&node[i].x,&node[i].y); 82 if(node[i].x>xx) xx=node[i].x; 83 if(node[i].x<nx) nx=node[i].x; 84 if(node[i].y>xy) xy=node[i].y; 85 if(node[i].y<ny) ny=node[i].y; 86 fw[i]=0; 87 } 88 long long li=0,ri=max(xy-ny,xx-nx); 89 while(li<=ri) 90 { 91 long long mid=(li+ri)>>1; 92 memset(fw,0,sizeof(fw)); 93 if(dfs(mid,1,0))ri=mid-1; 94 else li=mid+1; 95 } 96 printf("%lld\n",ri+1); 97 return 0; 98 }