1. 程式人生 > >bzoj1052 9.20考試 第二題 覆蓋問題

bzoj1052 9.20考試 第二題 覆蓋問題

tin input 平面 out mit class define long solved

1052: [HAOI2007]覆蓋問題

Time Limit: 10 Sec Memory Limit: 162 MB
Submit: 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

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 }
View Code

bzoj1052 9.20考試 第二題 覆蓋問題