1185: [HNOI2007]最小矩形覆盖
Time Limit: 10 Sec Memory Limit: 162 MBSec Special JudgeSubmit: 1795 Solved: 795
[Submit][Status][Discuss]
Description
思路{
先求凸包,发现矩形的一条边一定与凸多边形的一条边重合.
用类似旋转卡壳的方式即可求出对于这条边为底,最左端的点,最右端的点,最远的点,
这样直接更新答案就可以了.
}
#include<bits/stdc++.h>
#define RG register
#define il inline
#define N 50010
#define db double
using namespace std;
#define eps (1e-8)
db Ans=1e60;
struct point{
db x,y;
point() {}
point (db X,db Y):x(X),y(Y) {}
bool operator <(const point & a)const{return (fabs(y-a.y)<eps)?x<a.x:y<a.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 db & k)const{return point(k*x,k*y);}
db operator *(const point & a)const{return x*a.y-y*a.x;}
db operator ^(const point & a)const{return x*a.x+y*a.y;}
db len(){return sqrt(x*x+y*y);}
}p[N],st[N],q[4];
int n,top;
int cmp(db k){if(fabs(k)<eps)return 0;return k>0?1:-1;}
bool comp(const point & a,const point & b){return cmp(b.x-a.x)?a.x<b.x:a.y<b.y;}
void Graham(){
sort(p+1,p+n+1,comp);
for(int i=1;i<=n;++i){
while(top>1&&(st[top]-st[top-1])*(p[i]-st[top-1])<eps)top--;
st[++top]=p[i];
}int NN=top;st[++top]=p[n-1];
for(int i=n-2;i>1;i--){
while(top>NN&&(st[top]-st[top-1])*(p[i]-st[top-1])<eps)top--;
st[++top]=p[i];
}n=top;
for(int i=1;i<=top;++i)p[i]=st[i],p[0]=st[top];
}
void RC(){
int l(1),r(1),u(1);
db L,R,H,d;
for(int i=0;i<top;++i){
d=(p[i+1]-p[i]).len();
while((p[i+1]-p[i])*(p[u+1]-p[i])-(p[i+1]-p[i])*(p[u]-p[i])>-eps)u=(u+1)%n;
while(((p[r+1]-p[i])^(p[i+1]-p[i]))-((p[r]-p[i])^(p[i+1]-p[i]))>-eps)r=(r+1)%n;
if(!i)l=r;
while(((p[l+1]-p[i])^(p[i+1]-p[i]))-((p[l]-p[i])^(p[i+1]-p[i]))<eps)l=(l+1)%n;
L=((p[l]-p[i])^(p[i+1]-p[i]))/d;
R=((p[r]-p[i])^(p[i+1]-p[i]))/d;
H=((p[i+1]-p[i])*(p[u]-p[i]))/d;
if(H<0)H=-H;
db tmp=(R-L)*H;
if(tmp<Ans){
Ans=tmp;
q[0]=p[i]+(p[i+1]-p[i])*(R/d);
q[1]=q[0]+(p[r]-q[0])*(H/(q[0]-p[r]).len());
q[2]=q[1]-(q[0]-p[i])*((R-L)/(p[i]-q[0]).len());
q[3]=q[2]-(q[1]-q[0]);
}
}
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;++i)scanf("%lf%lf",&p[i].x,&p[i].y);
Graham();RC();printf("%.5lf\n",Ans);
int s(0);
for(int i=1;i<=3;++i)if(q[i]<q[s])s=i;
for(int i=0;i<=3;++i){
printf("%.5lf %.5lf\n",q[(i+s)%4].x,q[(i+s)%4].y);
}
return 0;
}