Description
给定一些点的坐标,要求求能够覆盖所有点的最小面积的矩形,
输出所求矩形的面积和四个顶点坐标
Input
第一行为一个整数n(3<=n<=50000)
从第2至第n+1行每行有两个浮点数,表示一个顶点的x和y坐标,不用科学计数法
Output
第一行为一个浮点数,表示所求矩形的面积(精确到小数点后5位),
接下来4行每行表示一个顶点坐标,要求第一行为y坐标最小的顶点,
其后按逆时针输出顶点坐标.如果用相同y坐标,先输出最小x坐标的顶点
Sample Input
6 1.0 3.00000
1 4.00000
2.0000 1
3 0.0000
3.00000 6
6.0 3.0
Sample Output
18.00000
3.00000 0.00000
6.00000 3.00000
3.00000 6.00000
0.00000 3.00000
Solution
说实话这个题笔者做的实在是非常难受身心俱疲。首先之前打过一遍然后挂了,怎么调都调不出来之后又重构代码,然后又是各种调不出来,之后过了样例,又是各种wa,什么特判都加完了之后终于是A掉了。。。
总体思路大致是这个样子,经过一系列奇奇怪怪的证明之后我们可以发现,我们要求的那个矩形一定有一条边在这些点的凸包的边上,然后旋转卡壳枚举边,求出来就可以了,代码非常难搞,细节非常多,笔者一开始被卡掉了0.0001的精度,结果找着黄学长的一顿乱改,结果改到最后,快长得一样了。。。。
Code
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#define ll long long
#define inf 50000000
#define re register
#define MAXN 50005
#define eps 1e-8
using namespace std;
double ans=1e60;
int n,top;
struct P{
double x,y;
P(){}
P(double _x,double _y):x(_x),y(_y){}
friend bool operator<(P a,P b){
return fabs(a.y-b.y)<eps?a.x<b.x:a.y<b.y;
}
friend bool operator==(P a,P b){
return fabs(a.x-b.x)<eps&&fabs(a.y<b.y)<eps;
}
friend bool operator!=(P a,P b){
return !(a==b);
}
friend P operator+(P a,P b){
return P(a.x+b.x,a.y+b.y);
}
friend P operator-(P a,P b){
return P(a.x-b.x,a.y-b.y);
}
friend double operator *(P a,P b){
return a.x*b.y-a.y*b.x;
}
friend P operator *(P a,double b){
return P(a.x*b,a.y*b);
}
friend double operator /(P a,P b){
return a.x*b.x+a.y*b.y;
}
friend double dis(P a){
return sqrt(a.x*a.x+a.y*a.y);
}
};
P p[MAXN],q[MAXN],t[5];
inline bool cmp(P a,P b)
{
double k=(a-p[1])*(b-p[1]);
if(fabs(k)<eps) return dis(p[1]-a)-dis(p[1]-b)<0;
return k>0;
}
inline void Graham()
{
for(re int i=2;i<=n;i++)
if(p[i]<p[1]) swap(p[i],p[1]);
sort(p+2,p+n+1,cmp);
q[++top]=p[1];
for(re int i=2;i<=n;i++){
while(top>1&&(q[top]-q[top-1])*(p[i]-q[top])<eps) top--;
q[++top]=p[i];
}
q[0]=q[top];
}
inline void solve()
{
int l=1,r=1,p=1;
double L,R,D,H;
for(re int i=0;i<top;i++){
D=dis(q[i]-q[i+1]);
while((q[i+1]-q[i])*(q[p+1]-q[i])-(q[i+1]-q[i])*(q[p]-q[i])>-eps) p=(p+1)%top;
while((q[i+1]-q[i])/(q[r+1]-q[i])-(q[i+1]-q[i])/(q[r]-q[i])>-eps) r=(r+1)%top;
if(i==0) l=r;
while((q[i+1]-q[i])/(q[l+1]-q[i])-(q[i+1]-q[i])/(q[l]-q[i])<eps)
l=(l+1)%top;
L=(q[i+1]-q[i])/(q[l]-q[i])/D;
R=(q[i+1]-q[i])/(q[r]-q[i])/D;
H=(q[i+1]-q[i])*(q[p]-q[i])/D;
if(H<0) H=-H;
double tmp=(R-L)*H;
if(tmp<ans)
{
ans=tmp;
t[0]=q[i]+(q[i+1]-q[i])*(R/D);
t[1]=t[0]+(q[r]-t[0])*(H/dis(t[0]-q[r]));
t[2]=t[1]-(t[0]-q[i])*((R-L)/dis(q[i]-t[0]));
t[3]=t[2]-(t[1]-t[0]);
}
}
}
int main()
{
cin>>n;
for(re int i=1;i<=n;i++)
scanf("%lf%lf",&p[i].x,&p[i].y);
Graham();
solve();
printf("%.5lf
" ,ans);
int fir=0;
for(re int i=1;i<=3;i++)
if(t[i]<t[fir])
fir=i;
for(re int i=0;i<=3;i++)
printf("%.5lf %.5lf
",fabs(t[(i+fir)%4].x)>1e-12?t[(i+fir)%4].x:0.00000,fabs(t[(i+fir)%4].y)>1e-12?t[(i+fir)%4].y:0.00000);
return 0;
}