bzoj1052 9.20考試 第二題 覆蓋問題
阿新 • • 發佈:2017-09-21
tin input 平面 out mit class define long solved
Submit: 2004 Solved: 937
[Submit][Status][Discuss]
第一行有一個正整數N,表示有多少棵樹。接下來有N行,第i+1行有2個整數Xi,Yi,表示第i棵樹的坐標,保證
不會有2個樹的坐標相同。
0 1
0 -1
1 0
-1 0
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
Output
一行,輸出最小的L值。
Sample Input
40 1
0 -1
1 0
-1 0
Sample Output
1HINT
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;View Code13 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 }
bzoj1052 9.20考試 第二題 覆蓋問題