bzoj1052 9.20考试 第二题 覆盖问题

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

 

posted @ 2017-09-21 19:17  Hzoi_joker  阅读(190)  评论(0编辑  收藏  举报