[HAOI2007]覆盖问题
题目描述
某人在山上种了N棵小树苗。冬天来了,温度急速下降,小树苗脆弱得不堪一击,于是树主人想用一些塑料薄膜把这些小树遮盖起来,经过一番长久的思考,他决定 用3个L*L的正方形塑料薄膜将小树遮起来。我们不妨将山建立一个平面直角坐标系,设第i棵小树的坐标为(Xi,Yi),3个L*L的正方形的边要求平行 与坐标轴,一个点如果在正方形的边界上,也算作被覆盖。当然,我们希望塑料薄膜面积越小越好,即求L最小值。
输入输出格式
输入格式:第一行有一个正整数N,表示有多少棵树。
接下来有N行,第i+1行有2个整数Xi,Yi,表示第i棵树的坐标,保证不会有2个树的坐标相同。
输出格式:一行,输出最小的L值。
输入输出样例
说明
数据范围
100%的数据,-1,000,000,000<=Xi,Yi<=1,000,000,000
30%的数据,N<=100
50%的数据,N<=2000
100%的数据,N<=20000
二分答案ans
求出最大的包括n个点的矩形
说明至少有一个正方形与外包矩形有两条边及以上相接,就是一个公共角
于是我们可以对于前两个正方形枚举与哪个角相接,对于第三个正方形判断就行了
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 using namespace std; 7 typedef long long lol; 8 struct Data 9 { 10 int top; 11 int x[20001],y[20001]; 12 }a; 13 int Minx,Miny,Maxx,Maxy,n,ans; 14 void cut(Data &b,int x1,int x2,int y1,int y2) 15 {int i; 16 int tot=0; 17 for(i=1;i<=b.top;i++) 18 { 19 if ((b.x[i]<x1||b.x[i]>x2)||(b.y[i]<y1||b.y[i]>y2)) 20 b.x[++tot]=b.x[i],b.y[tot]=b.y[i]; 21 } 22 b.top=tot; 23 } 24 void work(Data &b,int c,int mid) 25 {int i; 26 Maxx=-1e9;Minx=1e9; 27 Maxy=-1e9;Miny=1e9; 28 for (i=1;i<=b.top;i++) 29 { 30 Maxx=max(Maxx,b.x[i]);Minx=min(Minx,b.x[i]); 31 Maxy=max(Maxy,b.y[i]);Miny=min(Miny,b.y[i]); 32 } 33 if (c==1) 34 { 35 cut(b,Minx,Minx+mid,Miny,Miny+mid); 36 } 37 if (c==2) 38 { 39 cut(b,Minx,Minx+mid,Maxy-mid,Maxy); 40 } 41 if (c==3) 42 { 43 cut(b,Maxx-mid,Maxx,Maxy-mid,Maxy); 44 } 45 if (c==4) 46 { 47 cut(b,Maxx-mid,Maxx,Miny,Miny+mid); 48 } 49 } 50 bool check(int mid) 51 {int x,y,i,x1,y1,x2,y2; 52 Data b; 53 for (x=1;x<=4;x++) 54 { 55 for (y=1;y<=4;y++) 56 { 57 b.top=a.top; 58 for (i=1;i<=b.top;i++) 59 { 60 b.x[i]=a.x[i];b.y[i]=a.y[i]; 61 } 62 work(b,x,mid);work(b,y,mid); 63 x1=-1e9;x2=1e9; 64 y1=-1e9;y2=1e9; 65 for (i=1;i<=b.top;i++) 66 { 67 x1=max(x1,b.x[i]);x2=min(x2,b.x[i]); 68 y1=max(y1,b.y[i]);y2=min(y2,b.y[i]); 69 } 70 if (x1-x2<=mid&&y1-y2<=mid) return 1; 71 } 72 } 73 return 0; 74 } 75 int main() 76 {int i; 77 cin>>n; 78 for (i=1;i<=n;i++) 79 { 80 scanf("%d%d",&a.x[i],&a.y[i]); 81 } 82 a.top=n; 83 int l=0,r=1e9; 84 while (l<=r) 85 { 86 int mid=(l+r)/2; 87 if (check(mid)) ans=mid,r=mid-1; 88 else l=mid+1; 89 } 90 cout<<ans; 91 }