bzoj1185 [HNOI2007]最小矩形覆蓋 旋轉卡殼求凸包

[HNOI2007]最小矩形覆蓋

Time Limit: 10 Sec  Memory Limit: 162 MBSec  Special Judge
Submit: 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

Sample Output

18.00000
3.00000 0.00000
6.00000 3.00000
3.00000 6.00000
0.00000 3.00000

HINT

 

Source

[ Submit][ Status][ Discuss]


HOME Backios

 

首先有一個結論,矩形的一條邊必定在凸包上!!!
枚舉凸包上的邊
用旋轉卡殼在凸包上找矩形另外三點。。
差很少吧,其它三個點能夠找的吧,並且也是有單調性的。
 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 }
相關文章
相關標籤/搜索