题意:
分析:
这道题是旋转卡壳的一个典型问题
首先我们瞎蒙一个性质:
我们目标状态的矩形一定有一条边是凸包上的边(的延长线)
其实是可以证明的:
首先,最小矩形必然每条边上都有点
那么如果不是凸包上的边:
那么我们可以通过旋转这个矩形,使得这个矩形的某条边上不再有点
所以,我们只需要找出凸包,暴力枚举每条边,用旋转卡壳来确定这个矩形。
那么,如何卡壳呢?
很简单,我们考虑叉积和点积的几何意义:
叉积:可以求出一个点与一条线所构成的三角形面积。
点积:可以求出一条向量在另一条上的投影长度。
那么根据这两点,我们可以通过叉积找到离当前线段最远的点,通过点积找到离当前线段最左/右的点,通过这三个点和这条线段,我们就可以确定这个矩形了。当然,我们需要按照顺时针/逆时针的顺序依次枚举每条边,然后再贪心地确定三个特殊点即可。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<stack>
#include<cmath>
#define SF scanf
#define PF printf
#define MAXN 100010
#define EPS 1e-8
using namespace std;
struct node{
double x,y;
node(){}
node(double xx,double yy):x(xx),y(yy) {}
node operator + (const node &a) const {
return node(x+a.x,y+a.y);
}
node operator - (const node &a) const {
return node(x-a.x,y-a.y);
}
node operator * (const double &t) const {
return node(x*t,y*t);
}
double operator *(const node &a) const{
return x*a.x+y*a.y;
}
double operator ^(const node &a) const{
return x*a.y-y*a.x;
}
/*bool operator <(const node &a) const {
return y<a.y||(fabs(y-a.y)<EPS&&x<a.x);
}*/
bool operator <(const node &a) const {
return fabs(y-a.y)<EPS?x<a.x:y<a.y;
}
}p[MAXN],l1[MAXN],t[5];
stack<node> s1,s;
double ans=1e60;
int n,cnt1;
void solve(node a1[],int &cnt){
s.push(p[1]);
s1.push(p[1]);
s1.push(p[2]);
for(int i=3;i<=n;i++){
while(!s.empty()&&((p[i]-s.top())^(s1.top()-s.top()))<=0){
s.pop();
s1.pop();
}
s.push(s1.top());
s1.push(p[i]);
}
while(!s1.empty()){
a1[++cnt]=s1.top();
s1.pop();
}
while(!s.empty())
s.pop();
}
double len(node a){
return sqrt(a.x*a.x+a.y*a.y);
}
bool cmp(node a,node b){
return b<a;
}
void rc(){
int l=1,r=1,p=1;
double L,R,D,H;
for(int i=0;i<cnt1;i++)
{
D=len(l1[i]-l1[i+1]);
while((((l1[i+1]-l1[i])^(l1[p+1]-l1[i]))-((l1[i+1]-l1[i])^(l1[p]-l1[i]))) >-EPS)
p=(p+1)%cnt1;
while(((l1[i+1]-l1[i])*(l1[r+1]-l1[i]))-((l1[i+1]-l1[i])*(l1[r]-l1[i]))>-EPS)
r=(r+1)%cnt1;
if(i==0)
l=r;
while(((l1[i+1]-l1[i])*(l1[l+1]-l1[i]))-((l1[i+1]-l1[i])*(l1[l]-l1[i]))<EPS)
l=(l+1)%cnt1;
L=(l1[i+1]-l1[i])*(l1[l]-l1[i])/D;
R=(l1[i+1]-l1[i])*(l1[r]-l1[i])/D;
H=((l1[i+1]-l1[i])^(l1[p]-l1[i]))/D;
H=fabs(H);
double tmp=(R-L)*H;
if(tmp<ans){
ans=tmp;
t[0]=l1[i]+(l1[i+1]-l1[i])*(R/D);
t[1]=t[0]+(l1[r]-t[0])*(H/len(t[0]-l1[r]));
t[2]=t[1]-(t[0]-l1[i])*((R-L)/len(l1[i]-t[0]));
t[3]=t[2]-(t[1]-t[0]);
}
}
}
int main(){
SF("%d",&n);
for(int i=1;i<=n;i++)
SF("%lf%lf",&p[i].x,&p[i].y);
sort(p+1,p+1+n,cmp);
solve(l1,cnt1);
sort(p+1,p+1+n);
cnt1--;
solve(l1,cnt1);
cnt1--;
l1[0]=l1[cnt1];
/*for(int i=0;i<=cnt1;i++)
PF("[%.3lf %.3lf]\n",l1[i].x,l1[i].y);*/
rc();
PF("%.5lf\n",ans);
int fir=0;
for(int i=1;i<4;i++)
if(t[i]<t[fir])
fir=i;
for(int i=0;i<4;i++)
PF("%.5lf %.5lf\n",t[(i+fir)%4].x,t[(i+fir)%4].y);
}