bzoj1185: [HNOI2007]最小矩形覆盖

Description

bzoj1185: [HNOI2007]最小矩形覆盖 

bzoj1185: [HNOI2007]最小矩形覆盖

顺序枚举凸包上的边确定矩形一边,旋转卡壳确定在矩形另外三边上的点

#include<cstdio>
#include<cmath>
#include<algorithm>
typedef long double ld;
const ld _0=1e-7;
struct vec{ld x,y;};
struct line{vec p,v;};
vec operator+(vec a,vec b){return (vec){a.x+b.x,a.y+b.y};}
vec operator-(vec a,vec b){return (vec){a.x-b.x,a.y-b.y};}
vec operator*(vec a,ld x){return (vec){a.x*x,a.y*x};}
ld operator*(vec a,vec b){return a.x*b.y-a.y*b.x;}
bool operator<(vec a,vec b){return a*b>0;}
ld abs(vec a){return sqrt(a.x*a.x+a.y*a.y);}
vec operator&(line a,line b){return a.p+a.v*((b.v*(a.p-b.p))/(a.v*b.v));}
int n,p,p1,p2,p3,pa[4];
vec vs[50010],ps[100010],m;
ld ans=1e40;
vec as[4];
int main(){
    scanf("%d",&n);
    for(int i=0;i<n;i++)scanf("%llf%llf",&vs[i].x,&vs[i].y);
    for(int i=1;i<n;i++)if(vs[i].x<vs[p].x||vs[i].x==vs[p].x&&vs[i].y<vs[p].y)p=i;
    m=vs[p];
    for(int i=0;i<n;i++){
        vs[i]=vs[i]-m;
        if(abs(vs[i])<_0)vs[i--]=vs[--n];
    }
    std::sort(vs,vs+n);
    ps[0]=(vec){0,0};
    ps[p=1]=vs[0];
    for(int i=1;i<n;i++){
        while(p&&(ps[p]-ps[p-1])*(vs[i]-ps[p])<_0)--p;
        ps[++p]=vs[i];
    }
    n=p+1;
    for(int i=0;i<=n;i++)ps[i+n]=ps[i];
    int n0=n;
    n=n*2+1;
    for(p=0,p1=p2=p3=1;p<n0;p++){
        vec w=ps[p+1]-ps[p];
        if(abs(w)<_0)continue;
        while(p2<n&&w*(ps[p2+1]-ps[p])>w*(ps[p2]-ps[p]))++p2;
        ld x=w*(ps[p2]-ps[p])/abs(w);
        if(p2>p3)p3=p2;
        w=(vec){-w.y,w.x};
        while(p1<n&&w*(ps[p1+1]-ps[p])<w*(ps[p1]-ps[p]))++p1;
        while(p3<n&&w*(ps[p3+1]-ps[p])>w*(ps[p3]-ps[p]))++p3;
        ld y=w*(ps[p3]-ps[p])/abs(w)-w*(ps[p1]-ps[p])/abs(w);
        ld S=x*y;
        if(S<ans){
            ans=S;
            pa[0]=p;pa[1]=p1;pa[2]=p2;pa[3]=p3;
        }
    }
    p=pa[0];p1=pa[1];p2=pa[2];p3=pa[3];
    vec w=ps[p+1]-ps[p];
    line l0=(line){ps[p],w};
    line l2=(line){ps[p2],w};
    w=(vec){-w.y,w.x};
    line l1=(line){ps[p1],w};
    line l3=(line){ps[p3],w};
    as[0]=(l0&l1)+m;
    as[1]=(l1&l2)+m;
    as[2]=(l2&l3)+m;
    as[3]=(l3&l0)+m;
    p=0;
    for(int i=1;i<4;i++)if(as[i].y<as[p].y-_0||fabs(as[i].y-as[p].y)<_0&&as[i].x<as[p].x-_0)p=i;
    printf("%.5lf
",(double)ans);
    for(int i=0;i<4;i++)printf("%.5lf %.5lf
",(double)as[i+p&3].x,(double)as[i+p&3].y);
    return 0;
}