[HNOI2007]最小矩形覆盖
Time Limit: 10 Sec Memory Limit: 162 MBSec Special JudgeSubmit: 2081 Solved: 920
[Submit][Status][Discuss]
Description
给定一些点的坐标,要求求能够覆盖所有点的最小面积的矩形,
输出所求矩形的面积和四个顶点坐标
Input
第一行为一个整数n(3<=n<=50000)
从第2至第n+1行每行有两个浮点数,表示一个顶点的x和y坐标,不用科学计数法
Output
第一行为一个浮点数,表示所求矩形的面积(精确到小数点后5位),
接下来4行每行表示一个顶点坐标,要求第一行为y坐标最小的顶点,
其后按逆时针输出顶点坐标.如果用相同y坐标,先输出最小x坐标的顶点
Sample Input
6 1.0 3.00000
1 4.00000
2.0000 1
3 0.0000
3.00000 6
6.0 3.0
1 4.00000
2.0000 1
3 0.0000
3.00000 6
6.0 3.0
Sample Output
18.00000
3.00000 0.00000
6.00000 3.00000
3.00000 6.00000
0.00000 3.00000
3.00000 0.00000
6.00000 3.00000
3.00000 6.00000
0.00000 3.00000
HINT
Source
首先有一个结论,矩形的一条边一定在凸包上!!!
枚举凸包上的边
用旋转卡壳在凸包上找矩形另外三点。。
差不多吧,其它三个点可以找的吧,而且也是有单调性的。
1 #pragma GCC optimize(2) 2 #pragma G++ optimize(2) 3 #include<cstring> 4 #include<cmath> 5 #include<iostream> 6 #include<algorithm> 7 #include<cstdio> 8 9 #define eps 0.00000001 10 #define N 50007 11 using namespace std; 12 inline int read() 13 { 14 int x=0,f=1;char ch=getchar(); 15 while(!isdigit(ch)){if(ch==‘-‘)f=-1;ch=getchar();} 16 while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-‘0‘;ch=getchar();} 17 return x*f; 18 } 19 20 int n,tot; 21 double ans=1e60; 22 struct P 23 { 24 double x,y; 25 P(){} 26 P(double _x,double _y):x(_x),y(_y){} 27 friend bool operator<(P a,P b){return fabs(a.y-b.y)<eps?a.x<b.x:a.y<b.y;} 28 friend bool operator==(P a,P b){return fabs(a.x-b.x)<eps&&fabs(a.y-b.y)<eps;} 29 friend bool operator!=(P a,P b){return !(a==b);} 30 friend P operator+(P a,P b){return P(a.x+b.x,a.y+b.y);} 31 friend P operator-(P a,P b){return P(a.x-b.x,a.y-b.y);} 32 friend double operator*(P a,P b){return a.x*b.y-a.y*b.x;} 33 friend P operator*(P a,double b){return P(a.x*b,a.y*b);} 34 friend double operator/(P a,P b){return a.x*b.x+a.y*b.y;} 35 friend double dis(P a){return sqrt(a.x*a.x+a.y*a.y);} 36 }p[N],q[N],t[5]; 37 38 bool cmp(P a,P b) 39 { 40 double t=(a-p[1])*(b-p[1]); 41 if(fabs(t)<eps)return dis(p[1]-a)-dis(p[1]-b)<0; 42 return t>0; 43 } 44 void Graham() 45 { 46 for (int i=2;i<=n;i++) 47 if(p[i]<p[1])swap(p[i],p[1]); 48 sort(p+2,p+n+1,cmp); 49 q[++tot]=p[1]; 50 for (int i=2;i<=n;i++) 51 { 52 while(tot>1&&(q[tot]-q[tot-1])*(p[i]-q[tot])<eps)tot--; 53 q[++tot]=p[i]; 54 } 55 q[0]=q[tot];//凸包是一个回路。 56 } 57 void RC() 58 { 59 int l=1,r=1,p=1; 60 double L,R,D,H; 61 for (int i=0;i<tot;i++) 62 { 63 D=dis(q[i]-q[i+1]); 64 while((q[i+1]-q[i])*(q[p+1]-q[i])-(q[i+1]-q[i])*(q[p]-q[i])>-eps)p=(p+1)%tot; 65 while((q[i+1]-q[i])/(q[r+1]-q[i])-(q[i+1]-q[i])/(q[r]-q[i])>-eps)r=(r+1)%tot; 66 if(i==0)l=r; 67 while((q[i+1]-q[i])/(q[l+1]-q[i])-(q[i+1]-q[i])/(q[l]-q[i])<eps)l=(l+1)%tot; 68 L=(q[i+1]-q[i])/(q[l]-q[i])/D,R=(q[i+1]-q[i])/(q[r]-q[i])/D; 69 H=(q[i+1]-q[i])*(q[p]-q[i])/D; 70 if(H<0)H=-H; 71 double tmp=(R-L)*H; 72 if(tmp<ans) 73 { 74 ans=tmp; 75 t[0]=q[i]+(q[i+1]-q[i])*(R/D); 76 t[1]=t[0]+(q[r]-t[0])*(H/dis(t[0]-q[r])); 77 t[2]=t[1]-(t[0]-q[i])*((R-L)/dis(q[i]-t[0])); 78 t[3]=t[2]-(t[1]-t[0]); 79 } 80 } 81 } 82 int main() 83 { 84 n=read(); 85 for (int i=1;i<=n;i++) 86 scanf("%lf%lf",&p[i].x,&p[i].y); 87 Graham(); 88 RC(); 89 printf("%.5lf\n",ans); 90 int fir=0; 91 for (int i=1;i<=3;i++) 92 if(t[i]<t[fir])fir=i; 93 for (int i=0;i<=3;i++) 94 printf("%.5lf %.5lf\n",t[(i+fir)%4].x,t[(i+fir)%4].y); 95 }