题意
考虑矩形必定满足一条边和凸包重合(意会),于是我们枚举凸包的每一条边,考虑维护据该条边的最远点(p)、最左点(l)、最右点(r),这三个都可以旋转卡壳。
首先最远点是经典的求凸包直径问题,我们移动时比较当前和下一个三角形的大小即可。
之后考虑最左点和最右点,我们用点积求出投影长度来比较就好了。
code:
#include<bits/stdc++.h>
using namespace std;
const int maxn=50010;
const double eps=1e-12;
const double inf=1e9;
int n,m;
double ans=inf;
struct Point
{
double x,y;
inline double len(){return sqrt(x*x+y*y);}
Point operator+(const Point a)const{return (Point){x+a.x,y+a.y};}
Point operator-(const Point a)const{return (Point){x-a.x,y-a.y};}
Point operator*(const double k){return (Point){x*k,y*k};}
Point operator/(const double k){return (Point){x/k,y/k};}
double operator*(const Point a)const{return x*a.y-y*a.x;}
double operator&(const Point a)const{return x*a.x+y*a.y;}
}p[maxn],sta[maxn],ansp[5];
inline int dcmp(double x)
{
if(fabs(x)<=eps)return 0;
return x<0?-1:1;
}
inline bool cmp1(Point a,Point b){return !dcmp(a.y-b.y)?dcmp(a.x-b.x)<0:dcmp(a.y-b.y)<0;}
inline bool cmp2(Point a,Point b)
{
if(!dcmp(a.x)&&!dcmp(a.y))return 1;
else if(!dcmp(b.x)&&!dcmp(b.y))return 0;
else return atan2(a.y,a.x)<atan2(b.y,b.x);
}
inline Point get(Point a,Point b){return b-a;}
inline void build()
{
sort(p+1,p+n+1,cmp1);
for(int i=1;i<=n;i++)
{
while(m>1&&dcmp(get(sta[m-1],sta[m])*get(sta[m],p[i]))<=0)m--;
sta[++m]=p[i];
}
int tmp=m;
for(int i=n-1;i;i--)
{
while(m>tmp&&dcmp(get(sta[m-1],sta[m])*get(sta[m],p[i]))<=0)m--;
sta[++m]=p[i];
}
m--;sta[0]=sta[m];
}
inline void solve()
{
int l=1,r=1,p=1;
double L=0,R=0,H=0;
for(int i=0;i<m;i++)
{
while(dcmp(get(sta[i],sta[i+1])*get(sta[i],sta[p+1])-get(sta[i],sta[i+1])*get(sta[i],sta[p]))>=0)p=(p+1)%m;
while(dcmp((get(sta[i],sta[i+1])&get(sta[i],sta[r+1]))-(get(sta[i],sta[i+1])&get(sta[i],sta[r]))>=0))r=(r+1)%m;
if(!i)l=r;
while(dcmp((get(sta[i],sta[i+1])&get(sta[i],sta[l+1]))-(get(sta[i],sta[i+1])&get(sta[i],sta[l]))<=0))l=(l+1)%m;
double d=get(sta[i],sta[i+1]).len();
L=(get(sta[i],sta[i+1])&get(sta[i],sta[l]))/d;
R=(get(sta[i],sta[i+1])&get(sta[i],sta[r]))/d;
H=fabs(get(sta[i],sta[i+1])*get(sta[i],sta[p])/d);
double tmp=H*(R-L);
if(tmp<ans)
{
ans=tmp;
ansp[1]=sta[i]+get(sta[i],sta[i+1])*(R/d);
ansp[2]=ansp[1]+get(ansp[1],sta[r])*(H/get(ansp[1],sta[r]).len());
ansp[3]=ansp[2]+get(ansp[1],sta[i])*((R-L)/get(ansp[1],sta[i]).len());
ansp[4]=ansp[1]+get(ansp[1],sta[i])*((R-L)/get(ansp[1],sta[i]).len());
}
}
}
int main()
{
//freopen("test.in","r",stdin);
//freopen("test.out","w",stdout);
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%lf%lf",&p[i].x,&p[i].y);
build();solve();
printf("%.5lf
",ans+eps);
sort(ansp+1,ansp+4+1,cmp2);
for(int i=1;i<=4;i++)printf("%.5lf %.5lf
",ansp[i].x+eps,ansp[i].y+eps);
return 0;
}