【bzoj1185】[HNOI2007]最小矩形覆盖 (旋转卡壳)

给你一些点,让你用最小的矩形覆盖这些点

首先有一个结论,矩形的一条边一定在凸包上!!!
枚举凸包上的边
用旋转卡壳在凸包上找矩形另外三点。。。
注意精度问题
  1 #include<cstdio>
  2 #include<cmath>
  3 #include<ctime>
  4 #include<cstring>
  5 #include<iostream>
  6 #include<algorithm>
  7 #include<queue>
  8 #include<set>
  9 #define eps 1e-8
 10 #define inf 1000000000
 11 using namespace std;
 12 double ans=1e60;
 13 int n,top;
 14 struct P{
 15     double x,y;
 16     P(){}
 17     P(double _x,double _y):x(_x),y(_y){}
 18     friend bool operator<(P a,P b){
 19         return fabs(a.y-b.y)<eps?a.x<b.x:a.y<b.y;
 20     }
 21     friend bool operator==(P a,P b){
 22         return fabs(a.x-b.x)<eps&&fabs(a.y-b.y)<eps;
 23     }
 24     friend bool operator!=(P a,P b){
 25         return !(a==b);
 26     }
 27     friend P operator+(P a,P b){
 28         return P(a.x+b.x,a.y+b.y);
 29     }
 30     friend P operator-(P a,P b){
 31         return P(a.x-b.x,a.y-b.y);
 32     }
 33     friend double operator*(P a,P b){
 34         return a.x*b.y-a.y*b.x;
 35     }
 36     friend P operator*(P a,double b){
 37         return P(a.x*b,a.y*b);
 38     }
 39     friend double operator/(P a,P b){
 40         return a.x*b.x+a.y*b.y;
 41     }
 42     friend double dis(P a){
 43         return sqrt(a.x*a.x+a.y*a.y);
 44     }
 45 }p[50005],q[50005],t[5];
 46 bool cmp(P a,P b)
 47 {
 48     double t=(a-p[1])*(b-p[1]);
 49     if(fabs(t)<eps)return dis(p[1]-a)-dis(p[1]-b)<0;
 50     return t>0;
 51 }
 52 void graham()
 53 {
 54     for(int i=2;i<=n;i++)
 55         if(p[i]<p[1])
 56             swap(p[i],p[1]);
 57     sort(p+2,p+n+1,cmp);
 58     q[++top]=p[1];
 59     for(int i=2;i<=n;i++)
 60     {
 61         while(top>1&&(q[top]-q[top-1])*(p[i]-q[top])<eps)top--;
 62         q[++top]=p[i];
 63     }
 64     q[0]=q[top];
 65 }
 66 void RC()
 67 {
 68     int l=1,r=1,p=1;
 69     double L,R,D,H;
 70     for(int i=0;i<top;i++)
 71     {
 72         D=dis(q[i]-q[i+1]);
 73         while((q[i+1]-q[i])*(q[p+1]-q[i])-(q[i+1]-q[i])*(q[p]-q[i])>-eps)p=(p+1)%top;
 74         while((q[i+1]-q[i])/(q[r+1]-q[i])-(q[i+1]-q[i])/(q[r]-q[i])>-eps)r=(r+1)%top;
 75         if(i==0)l=r;
 76         while((q[i+1]-q[i])/(q[l+1]-q[i])-(q[i+1]-q[i])/(q[l]-q[i])<eps)l=(l+1)%top;
 77         L=(q[i+1]-q[i])/(q[l]-q[i])/D,R=(q[i+1]-q[i])/(q[r]-q[i])/D;
 78         H=(q[i+1]-q[i])*(q[p]-q[i])/D;
 79         if(H<0)H=-H;
 80         double tmp=(R-L)*H;
 81         if(tmp<ans)
 82         {
 83             ans=tmp;
 84             t[0]=q[i]+(q[i+1]-q[i])*(R/D);
 85             t[1]=t[0]+(q[r]-t[0])*(H/dis(t[0]-q[r]));
 86             t[2]=t[1]-(t[0]-q[i])*((R-L)/dis(q[i]-t[0]));
 87             t[3]=t[2]-(t[1]-t[0]);
 88         }
 89     }
 90 }
 91 int main()
 92 {
 93     scanf("%d",&n);
 94     for(int i=1;i<=n;i++)
 95         scanf("%lf%lf",&p[i].x,&p[i].y);
 96     graham();
 97     RC();
 98     printf("%.5lf\n",ans);
 99     int fir=0;
100     for(int i=1;i<=3;i++)
101         if(t[i]<t[fir])
102             fir=i;
103     for(int i=0;i<=3;i++)
104         printf("%.5lf %.5lf\n",t[(i+fir)%4].x,t[(i+fir)%4].y);
105     return 0;
106 }

 

posted @ 2017-10-18 21:22  抓不住Jerry的Tom  阅读(170)  评论(0编辑  收藏  举报