[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 }

 

posted @ 2018-01-12 10:39  Z-Y-Y-S  阅读(286)  评论(0编辑  收藏  举报