Description
顺序枚举凸包上的边确定矩形一边,旋转卡壳确定在矩形另外三边上的点
#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\n",(double)ans); for(int i=0;i<4;i++)printf("%.5lf %.5lf\n",(double)as[i+p&3].x,(double)as[i+p&3].y); return 0; }