某人在山上种了 N 棵小树苗。冬天来了,温度急速下降,小树苗脆弱得不堪一击,于是树主人想用一些塑料薄膜把这些小树遮盖起来,经过一番长久的思考,他决定用 3 个 L*L 的正方形塑料薄膜将小树遮起来。我们不妨将山建立一个平面直角坐标系,设第i棵小树的坐标为 (Xi,Yi),3 个 L*L 的正方形的边要求平行于坐标轴,一个点如果在正方形的边界上,也算作被覆盖。当然,我们希望塑料薄膜面积越小越好,即求 L 最小值。
数据范围
100%的数据,-1,000,000,000<=Xi,Yi<=1,000,000,000
30%的数据,N<=100
50%的数据,N<=2000
100%的数据,N<=20000
补充:L 是一个整数
由于是要求用三个边长相同的正方形覆盖所有的点,可以考虑二分正方形的变长,那么剩下的问题就是怎么根据一个给定的变长,确定是否三个这样的正方形能够将素有的点覆盖完
先用一个尽量小的矩形区域将没有覆盖的点框起来,那么,我们用于覆盖的正方形必然有一个顶角在矩形的四个顶角之一,这样覆盖是最优的
那么,我们只需要 DFS 一遍即可,DFS 的深度为 2,每次 DFS 有四个选择方向,这样做在时间上完全可行
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 5 using namespace std; 6 7 typedef long long LL; 8 9 const int N=20005; 10 const LL INF=(1LL)<<60; 11 12 struct Point { 13 LL x, y; 14 } p[N]; 15 int n, vs[N]; 16 17 void Find(LL &Maxx, LL &Minx, LL &Maxy, LL &Miny) { 18 Maxx=Maxy=-INF, Minx=Miny=INF; 19 for(int i=0; i<n; i++) if(!vs[i]) { 20 Maxx=max(Maxx, p[i].x); 21 Maxy=max(Maxy, p[i].y); 22 Minx=min(Minx, p[i].x); 23 Miny=min(Miny, p[i].y); 24 } 25 } 26 27 bool DFS(LL R, int dep) { 28 LL Maxx, Minx, Maxy, Miny; 29 Find(Maxx, Minx, Maxy, Miny); 30 if(Maxx==-INF) return true; 31 if(dep==3) { 32 if(max(Maxx-Minx, Maxy-Miny)<=R) return true; 33 return false; 34 } 35 36 for(int i=0; i<n; i++) if(!vs[i]) { 37 if(p[i].x>=Maxx-R && p[i].x<=Maxx && p[i].y>=Maxy-R && p[i].y<=Maxy) vs[i]=dep; 38 } 39 if(DFS(R, dep+1)) return true; 40 for(int i=0; i<n; i++) if(vs[i]==dep) vs[i]=0; 41 42 for(int i=0; i<n; i++) if(!vs[i]) { 43 if(p[i].x>=Maxx-R && p[i].x<=Maxx && p[i].y>=Miny && p[i].y<=Miny+R) vs[i]=dep; 44 } 45 if(DFS(R, dep+1)) return true; 46 for(int i=0; i<n; i++) if(vs[i]==dep) vs[i]=0; 47 48 for(int i=0; i<n; i++) if(!vs[i]) { 49 if(p[i].x>=Minx && p[i].x<=Minx+R && p[i].y>=Miny && p[i].y<=Miny+R) vs[i]=dep; 50 } 51 if(DFS(R, dep+1)) return true; 52 for(int i=0; i<n; i++) if(vs[i]==dep) vs[i]=0; 53 54 for(int i=0; i<n; i++) if(!vs[i]) { 55 if(p[i].x>=Minx && p[i].x<=Minx+R && p[i].y>=Maxy-R && p[i].y<=Maxy) vs[i]=dep; 56 } 57 if(DFS(R, dep+1)) return true; 58 for(int i=0; i<n; i++) if(vs[i]==dep) vs[i]=0; 59 60 return false; 61 } 62 63 bool check(LL R) { 64 fill(vs, vs+n, 0); 65 return DFS(R, 1); 66 } 67 68 int main() { 69 while(scanf("%d", &n)!=EOF) { 70 for(int i=0; i<n; i++) { 71 scanf("%lld%lld", &p[i].x, &p[i].y); 72 vs[i]=0; 73 } 74 LL Maxx, Minx, Maxy, Miny; 75 Find(Maxx, Minx, Maxy, Miny); 76 LL L=0, R=max(Maxx-Minx, Maxy-Miny); 77 while(L<R) { 78 int mid=(L+R)>>1; 79 if(check(mid+1)) R=mid; 80 else L=mid+1; 81 } 82 if(!check(L)) L++; 83 printf("%lld\n", L); 84 } 85 return 0; 86 }