题目大意:最小矩形覆盖
首先有一个结论:凸包上一定有一条边与矩形的一条边重合
证明:如果不存在一条边与矩形的一条边重合,那么我将这个矩形旋转一下一定会比之前更小
于是我们枚举其中一条边,对其余三个点卡壳即可
这旋转卡壳写的真叫一个卡壳- - 还好1A掉了- -
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 50500
#define EPS 1e-7
using namespace std;
struct Point{
double x,y;
Point() {}
Point(double _,double __):
x(_),y(__) {}
friend istream& operator >> (istream &_,Point &p)
{
scanf("%lf%lf",&p.x,&p.y);
return _;
}
bool operator < (const Point &p) const
{
if(fabs(x-p.x)<EPS)
return y<p.y;
return x<p.x;
}
Point operator + (const Point &p) const
{
return Point(x+p.x,y+p.y);
}
Point operator - (const Point &p) const
{
return Point(x-p.x,y-p.y);
}
double operator * (const Point &p) const
{
return x*p.y-y*p.x;
}
Point operator * (const double &rate) const
{
return Point(x*rate,y*rate);
}
friend ostream& operator << (ostream& _,const Point &p)
{
printf("%.5lf %.5lf",p.x,p.y);
return _;
}
}points[M];
struct Line{
Point p,v;
Line() {}
Line(const Point &_,const Point &__):
p(_),v(__) {}
};
int n,top;
double ans=1e15;
Point ans_points[4];
Point *stack[M<<1];
Point Get_Intersection(const Line &l1,const Line &l2)
{
Point u=l1.p-l2.p;
double temp=(l2.v*u)/(l1.v*l2.v);
return l1.p+l1.v*temp;
}
void Get_Convex_Hull()
{
static Point *stack[M];
int i,top=0;
for(i=1;i<=n;i++)
{
while( top>=2 && (*stack[top]-*stack[top-1])*(points[i]-*stack[top])>=-EPS )
stack[top--]=0x0;
stack[++top]=&points[i];
}
for(i=1;i<=top;i++)
::stack[++::top]=stack[i];
top=0;
for(i=1;i<=n;i++)
{
while( top>=2 && (*stack[top]-*stack[top-1])*(points[i]-*stack[top])<=EPS )
stack[top--]=0x0;
stack[++top]=&points[i];
}
for(i=top-1;i>1;i--)
::stack[++::top]=stack[i];
int limit=::top;
for(i=1;i<=limit;i++)
::stack[++::top]=::stack[i];
::stack[++::top]=::stack[1];
}
void Rotating_Calipers()
{
int limit=top>>1;
Point **p1,**p2,**p3,**p4;
p1=stack+1;
Point v1=(**(p1+1)-**p1);
Point v2(v1.y,-v1.x);
Point v3(v2.y,-v2.x);
Point v4(v3.y,-v3.x);
for(p2=p1;(**(p2+1)-**p2)*v2<0;p2++);
for(p3=p2;(**(p3+1)-**p3)*v3<0;p3++);
for(p4=p3;(**(p4+1)-**p4)*v4<0;p4++);
for(;p1<=stack+limit;p1++)
{
v1=(**(p1+1)-**p1);
v2=Point(v1.y,-v1.x);
v3=Point(v2.y,-v2.x);
v4=Point(v3.y,-v3.x);
for(;(**(p2+1)-**p2)*v2<0;p2++);
for(;(**(p3+1)-**p3)*v3<0;p3++);
for(;(**(p4+1)-**p4)*v4<0;p4++);
Point temp_points[4];
Line l1(**p1,v1);
Line l2(**p2,v2);
Line l3(**p3,v3);
Line l4(**p4,v4);
temp_points[0]=Get_Intersection(l1,l4);
temp_points[1]=Get_Intersection(l4,l3);
temp_points[2]=Get_Intersection(l3,l2);
temp_points[3]=Get_Intersection(l2,l1);
double area=(temp_points[1]-temp_points[0])*(temp_points[3]-temp_points[0]);
if(area<ans)
memcpy(ans_points,temp_points,sizeof ans_points),ans=area;
}
}
int main()
{
int i;
cin>>n;
for(i=1;i<=n;i++)
cin>>points[i];
sort(points+1,points+n+1);
Get_Convex_Hull();
Rotating_Calipers();
printf("%.5lf\n",ans);
int st=0;
for(i=1;i<4;i++)
if( ans_points[i].y<ans_points[st].y ||
fabs(ans_points[i].y-ans_points[st].y)<EPS && ans_points[i].x<ans_points[st].x )
st=i;
for(i=0;i<4;i++)
cout<<ans_points[i+st&3]<<endl;
return 0;
}