[HNOI2007]最小矩形覆盖
题目描述
给定一些点的坐标,要求求能够覆盖所有点的最小面积的矩形,输出所求矩形的面积和四个顶点坐标
输入输出格式
输入格式:
第一行为一个整数n(3<=n<=50000),从第2至第n+1行每行有两个浮点数,表示一个顶点的x和y坐标,不用科学计数法
输出格式:
第一行为一个浮点数,表示所求矩形的面积(精确到小数点后5位),接下来4行每行表示一个顶点坐标,要求第一行为y坐标最小的顶点,其后按逆时针输出顶点坐标.如果用相同y坐标,先输出最小x坐标的顶点
输入输出样例
输入样例#1: 复制
6
1.0 3.00000 1 4.00000 2.0000 1 3 0.0000 3.00000 6 6.0 3.0
输出样例#1: 复制
18.00000 3.00000 0.00000 6.00000 3.00000 3.00000 6.00000 0.00000 3.00000
最小的覆盖矩形肯定有边在凸包上
先求出凸包,然后枚举凸包上的边为直线构造矩形
用单调栈求出离该直线最远的点,左边最远的点和右边最远的点
就可以算出矩形的四个点
有可能输出-0.0000,所以要特判
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 using namespace std; 7 typedef long double ld; 8 struct point 9 { 10 ld x,y; 11 }p[50005],s[50005]; 12 point ansp[5]; 13 ld eps=1e-10,res,ans; 14 int n,top; 15 ld cross(point a,point b) 16 { 17 return a.x*b.y-b.x*a.y; 18 } 19 point operator *(point a,double b) 20 { 21 return (point){a.x*b,a.y*b}; 22 } 23 point operator -(point a,point b) 24 { 25 return (point){a.x-b.x,a.y-b.y}; 26 } 27 point operator +(point a,point b) 28 { 29 return (point){a.x+b.x,a.y+b.y}; 30 } 31 ld dot(point a,point b) 32 { 33 return a.x*b.x+a.y*b.y; 34 } 35 ld dist(point a) 36 { 37 return sqrt(a.x*a.x+a.y*a.y); 38 } 39 int dcmp(ld x) 40 { 41 if (x<-eps) return -1; 42 if (x>eps) return 1; 43 return 0; 44 } 45 bool cmp(point a,point b) 46 { 47 return (a.y<b.y)||(a.y==b.y&&a.x<b.x); 48 } 49 bool cmp2(point a,point b) 50 { 51 int t=dcmp(cross((p[1]-a),(p[1]-b))); 52 if (t==0) return dist(p[1]-a)<dist(p[1]-b); 53 return t>0; 54 } 55 bool cmp3(point a,point b) 56 { 57 return atan2(a.y-ansp[1].y,a.x-ansp[1].x)<atan2(b.y-ansp[1].y,b.x-ansp[1].x); 58 } 59 void graham() 60 {int i; 61 sort(p+1,p+n+1,cmp); 62 sort(p+2,p+n+1,cmp2); 63 s[++top]=p[1];s[++top]=p[2]; 64 for (i=3;i<=n;i++) 65 { 66 while (top>1&&dcmp(cross((p[i]-s[top-1]),(s[top]-s[top-1])))>=0) top--; 67 s[++top]=p[i]; 68 } 69 } 70 void solve() 71 {int i; 72 int pos=2,r=2,l; 73 s[top+1]=s[1]; 74 for (i=1;i<=top;i++) 75 { 76 ld D=dist(s[i+1]-s[i]); 77 while (dcmp(cross((s[i+1]-s[i]),(s[pos+1]-s[i]))-cross((s[i+1]-s[i]),(s[pos]-s[i])))>0) pos=pos%top+1; 78 while (dcmp(dot(s[i+1]-s[i],s[r+1]-s[i])-dot(s[i+1]-s[i],s[r]-s[i]))>=0) r=r%top+1; 79 if (i==1) l=r; 80 while (dcmp(dot(s[i+1]-s[i],s[l+1]-s[i])-dot(s[i+1]-s[i],s[l]-s[i]))<=0) l=l%top+1; 81 ld L=dot(s[l]-s[i],s[i+1]-s[i])/D; 82 ld R=dot(s[i+1]-s[i],s[r]-s[i])/D; 83 ld H=cross((s[i+1]-s[i]),(s[pos]-s[i]))/D; 84 res=(R-L)*H;if (res<0) res=-res; 85 if (dcmp(res-ans)<0) 86 { 87 ans=res; 88 ansp[1]=s[i]+(s[i+1]-s[i])*(L/D); 89 ansp[2]=s[i]+(s[i+1]-s[i])*(R/D); 90 ansp[3]=ansp[1]+(s[l]-ansp[1])*(H/dist(s[l]-ansp[1])); 91 ansp[4]=ansp[2]+(s[r]-ansp[2])*(H/dist(s[r]-ansp[2])); 92 if (dcmp(ansp[1].x)==0) ansp[1].x=fabs(ansp[1].x); 93 if (dcmp(ansp[1].y)==0) ansp[1].y=fabs(ansp[1].y); 94 if (dcmp(ansp[2].x)==0) ansp[2].x=fabs(ansp[2].x); 95 if (dcmp(ansp[2].y)==0) ansp[2].y=fabs(ansp[2].y); 96 if (dcmp(ansp[3].x)==0) ansp[3].x=fabs(ansp[3].x); 97 if (dcmp(ansp[3].y)==0) ansp[3].y=fabs(ansp[3].y); 98 if (dcmp(ansp[4].x)==0) ansp[4].x=fabs(ansp[4].x); 99 if (dcmp(ansp[4].y)==0) ansp[4].y=fabs(ansp[4].y); 100 } 101 } 102 } 103 int main() 104 {int i; 105 cin>>n; 106 ans=2e9; 107 for (i=1;i<=n;i++) 108 { 109 scanf("%Lf%Lf",&p[i].x,&p[i].y); 110 } 111 graham(); 112 solve(); 113 printf("%.5Lf\n",ans); 114 sort(ansp+1,ansp+5,cmp); 115 sort(ansp+2,ansp+5,cmp3); 116 for (i=1;i<=4;i++) 117 printf("%.5Lf %.5Lf\n",ansp[i].x,ansp[i].y); 118 }