###### 雯舞

Love three things int he world -- Manchery

###### [旋转卡壳] BZOJ 1185 [HNOI2007]最小矩形覆盖 && 2218 Uva10173 Smallest Bounding Rectangle

1185

#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<cstring>
#define cl(x) memset(x,0,sizeof(x))
#define eps 1e-6
using namespace std;
typedef long double ld;

inline int dcmp(ld a,ld b)
{
if (fabs(a-b)<eps) return 0;
if (a<b) return -1; return 1;
}

struct Point{
ld x,y;
Point(ld x=0,ld y=0):x(x),y(y) { }
bool operator < (const Point &b) const{
return dcmp(x,b.x)<0 || (dcmp(x,b.x)==0 && dcmp(y,b.y)<0);
}
}P[50005],H[50005];
ld s[50005];

int n,cnt;

inline ld Dot(Point p1,Point p2,Point p0)
{
return (p1.x-p0.x)*(p2.x-p0.x)+(p1.y-p0.y)*(p2.y-p0.y);
}

inline ld Cross(Point p1,Point p2,Point p0)
{
return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);
}

inline ld Dist(Point p1,Point p2)
{
return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
}

inline ld Dist(Point p1,Point p2,Point p0)
{
return fabs(Cross(p1,p2,p0)/Dist(p1,p2));
}

inline ld Area(Point p1,Point p2,Point p0)
{
return fabs(Cross(p1,p2,p0))/2;
}

inline void Qhull(int l,int r,Point a,Point b)
{
int i=l-1,j=r+1,x=l;
for (int k=l;k<=r;k++)
if (dcmp(s[k],s[x])>0 || (dcmp(s[x],s[k])==0 && P[x]<P[k]))
x=k;
Point y=P[x];
for (int k=l;k<=r;k++)
{
s[++i]=Cross(P[k],a,y);
if (dcmp(s[i],0)>0) swap(P[k],P[i]); else s[i--]=0;
}
for (int k=r;k>=l;k--)
{
s[--j]=Cross(P[k],y,b);
if (dcmp(s[j],0)>0) swap(P[k],P[j]); else s[j++]=0;
}
if (l<=i) Qhull(l,i,a,y);
H[++cnt]=y;
if (j<=r) Qhull(j,r,y,b);
}

Point AP[5];

inline bool cmp(Point a,Point b)
{
return a.x*b.y-b.x*a.y>0;
}

inline void Sort()
{
int k=1;
for (int i=2;i<=4;i++)
if (AP[i].y<AP[k].y || (AP[i].y==AP[k].y && AP[i].x<AP[k].y))
k=i;
swap(AP[1],AP[k]);
sort(AP+2,AP+5,cmp);
}

struct Line{
ld k,b;
ld x;
};

inline Point Cha(Line a,Line b)
{
if (a.k<-1e100 && a.b>1e100)
return Point(a.x,b.k*a.x+b.b);
if (b.k<-1e100 && b.b>1e100)
return Point(b.x,a.k*b.x+a.b);
ld x=(b.b-a.b)/(a.k-b.k);
return Point(x,a.k*x+a.b);
}

inline void Get(Point A,Point B,Point C,Point D,Point E)
{
Line Li1,Li2,Li3,Li4;
if (dcmp(A.x,B.x))
Li1.k=(B.y-A.y)/(B.x-A.x),Li1.b=A.y-A.x*Li1.k;
else
Li1.k=-1e130,Li1.b=1e130,Li1.x=A.x;
if (dcmp(Li1.k,0))
{
Li2.k=-1/Li1.k;
Li2.k=dcmp(Li2.k,0)?Li2.k:0.0;
Li2.b=C.y-C.x*Li2.k;
}
else
Li2.k=-1e130,Li2.b=1e130,Li2.x=C.x;
if (dcmp(Li1.k,0))
Li3.k=-1/Li1.k,Li3.k=dcmp(Li3.k,0)?Li3.k:0.0,Li3.b=D.y-D.x*Li3.k;
else
Li3.k=-1e130,Li3.b=1e130,Li3.x=D.x;
if (fabs(Li1.k)<1e100)
Li4.k=Li1.k,Li4.b=E.y-E.x*Li4.k;
else
Li4=Li1,Li4.x=E.x;
AP[1]=Cha(Li1,Li2);
AP[2]=Cha(Li1,Li3);
AP[3]=Cha(Li4,Li2);
AP[4]=Cha(Li4,Li3);
}

int main()
{
ld ans,tmp,A,B; double xx,yy;
Point X,Y,C,D;
int L1,L2,L3;
freopen("t.in","r",stdin);
freopen("t.out","w",stdout);
int x=1;
scanf("%d",&n);
for (int i=1;i<=n;i++)
{
scanf("%lf%lf",&xx,&yy);
P[i].x=xx; P[i].y=yy;
if (P[i]<P[x]) x=i;
}
if (n==3)
{
ld ret=1e20;
if (dcmp(ret,Dist(P[1],P[2])*Dist(P[1],P[2],P[3]))<0)
ret=Dist(P[1],P[2])*Dist(P[1],P[2],P[3]),Get(P[1],P[2],P[1],P[2],P[3]);
if (dcmp(ret,Dist(P[2],P[3])*Dist(P[2],P[3],P[1]))<0)
ret=Dist(P[2],P[3])*Dist(P[2],P[3],P[1]),Get(P[2],P[3],P[2],P[3],P[1]);
if (dcmp(ret,Dist(P[1],P[3])*Dist(P[1],P[3],P[2]))<0)
ret=Dist(P[1],P[3])*Dist(P[1],P[3],P[2]),Get(P[1],P[3],P[1],P[3],P[2]);
Sort();
printf("%.5lf\n",(double)ret);
for (int i=1;i<=4;i++)
printf("%.5lf %.5lf\n",(double)AP[i].x,(double)AP[i].y);
return 0;
}
swap(P[1],P[x]);
H[++cnt]=P[1];
Qhull(2,n,P[1],P[1]);
n=cnt;
for (int i=1;i<=cnt;i++)
P[i]=H[i];
Y=H[n]; X=H[1];
L1=2;
for (int i=3;i<n;i++)
if (dcmp(Dist(X,Y,P[i]),Dist(X,Y,P[L1]))>0)
L1=i;
L2=2;
for (int i=3;i<n;i++)
if (dcmp(Dot(Y,P[i],X)/Dist(X,Y),Dot(Y,P[L2],X)/Dist(X,Y))<0)
L2=i;
L3=2;
for (int i=3;i<n;i++)
if (dcmp(Dot(X,P[i],Y)/Dist(X,Y),Dot(X,P[L3],Y)/Dist(X,Y))<0)
L3=i;
B=Dist(X,Y,P[L1]);
A=Dist(X,Y);
C=X;
tmp=Dot(Y,P[L2],X)/Dist(X,Y);
if (dcmp(tmp,0.0)<0) A-=tmp,C=P[L2];
D=Y;
tmp=Dot(X,P[L3],Y)/Dist(X,Y);
if (dcmp(tmp,0.0)<0) A-=tmp,D=P[L3];
ans=A*B; Get(X,Y,C,D,P[L1]);
for (int i=1;i<n;i++)
{
Y=P[i]; X=P[i+1];
while (dcmp(Dist(X,Y,P[L1]),Dist(X,Y,P[L1%n+1]))<0)
L1=L1%n+1;
while (dcmp(Dot(Y,P[L2%n+1],X)/Dist(X,Y),Dot(Y,P[L2],X)/Dist(X,Y))<0)
L2=L2%n+1;
while (dcmp(Dot(X,P[L3%n+1],Y)/Dist(X,Y),Dot(X,P[L3],Y)/Dist(X,Y))<0)
L3=L3%n+1;
B=Dist(X,Y,P[L1]);
A=Dist(X,Y);
C=X;
tmp=Dot(Y,P[L2],X)/Dist(X,Y);
if (dcmp(tmp,0.0)<0) A-=tmp,C=P[L2];
D=Y;
tmp=Dot(X,P[L3],Y)/Dist(X,Y);
if (dcmp(tmp,0.0)<0) A-=tmp,D=P[L3];
if (dcmp(ans,A*B)>0)
ans=A*B,Get(X,Y,C,D,P[L1]);
}
Sort();
printf("%.5lf\n",(double)ans);
for (int i=1;i<=4;i++)
{
AP[i].x=dcmp(AP[i].x,0)?AP[i].x:0;
AP[i].y=dcmp(AP[i].y,0)?AP[i].y:0;
printf("%.5lf %.5lf\n",(double)AP[i].x,(double)AP[i].y);
}
return 0;
}

2218

#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<cstring>
#define cl(x) memset(x,0,sizeof(x))
#define eps 1e-6
using namespace std;
typedef long double ld;

inline int dcmp(ld a,ld b)
{
if (fabs(a-b)<eps) return 0;
if (a<b) return -1; return 1;
}

struct Point{
ld x,y;
bool operator < (const Point &b) const{
return dcmp(x,b.x)<0 || (dcmp(x,b.x)==0 && dcmp(y,b.y)<0);
}
}P[1005],H[1005];
ld s[1005];

int n,cnt;

inline ld Dot(Point p1,Point p2,Point p0)
{
return (p1.x-p0.x)*(p2.x-p0.x)+(p1.y-p0.y)*(p2.y-p0.y);
}

inline ld Cross(Point p1,Point p2,Point p0)
{
return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);
}

inline ld Dist(Point p1,Point p2)
{
return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
}

inline ld Dist(Point p1,Point p2,Point p0)
{
return fabs(Cross(p1,p2,p0)/Dist(p1,p2));
}

inline ld Area(Point p1,Point p2,Point p0)
{
return fabs(Cross(p1,p2,p0))/2;
}

inline void Qhull(int l,int r,Point a,Point b)
{
int i=l-1,j=r+1,x=l;
for (int k=l;k<=r;k++)
if (dcmp(s[k],s[x])>0 || (dcmp(s[x],s[k])==0 && P[x]<P[k]))
x=k;
Point y=P[x];
for (int k=l;k<=r;k++)
{
s[++i]=Cross(P[k],a,y);
if (dcmp(s[i],0)>0) swap(P[k],P[i]); else s[i--]=0;
}
for (int k=r;k>=l;k--)
{
s[--j]=Cross(P[k],y,b);
if (dcmp(s[j],0)>0) swap(P[k],P[j]); else s[j++]=0;
}
if (l<=i) Qhull(l,i,a,y);
H[++cnt]=y;
if (j<=r) Qhull(j,r,y,b);
}

int main()
{
ld ans,tmp,A,B; double xx,yy;
Point X,Y;
int L1,L2,L3;
freopen("t.in","r",stdin);
freopen("t.out","w",stdout);
while (1)
{
int x=1;
scanf("%d",&n); if (n==0) break;
for (int i=1;i<=n;i++)
{
scanf("%lf%lf",&xx,&yy);
P[i].x=xx; P[i].y=yy;
if (P[i]<P[x]) x=i;
}
if (n<=3)
{
if (n==1 || n==2)
printf("%.4lf\n",0.0);
else if (n==3)
{
ld ret=1e20;
ret=min(ret,Dist(P[1],P[2])*Dist(P[1],P[2],P[3]));
ret=min(ret,Dist(P[2],P[3])*Dist(P[2],P[3],P[1]));
ret=min(ret,Dist(P[1],P[3])*Dist(P[1],P[3],P[2]));
printf("%.4lf\n",(double)ret);
}
cl(P); cl(H); cnt=0; cl(s);
continue;
}
swap(P[1],P[x]);
H[++cnt]=P[1];
Qhull(2,n,P[1],P[1]);
n=cnt;
for (int i=1;i<=cnt;i++)
P[i]=H[i];
Y=H[n]; X=H[1];
L1=2;
for (int i=3;i<n;i++)
if (dcmp(Dist(X,Y,P[i]),Dist(X,Y,P[L1]))>0)
L1=i;
L2=2;
for (int i=3;i<n;i++)
if (dcmp(Dot(Y,P[i],X)/Dist(X,Y),Dot(Y,P[L2],X)/Dist(X,Y))<0)
L2=i;
L3=2;
for (int i=3;i<n;i++)
if (dcmp(Dot(X,P[i],Y)/Dist(X,Y),Dot(X,P[L3],Y)/Dist(X,Y))<0)
L3=i;
B=Dist(X,Y,P[L1]);
A=Dist(X,Y);
tmp=Dot(Y,P[L2],X)/Dist(X,Y);
if (dcmp(tmp,0.0)<0) A-=tmp;
tmp=Dot(X,P[L3],Y)/Dist(X,Y);
if (dcmp(tmp,0.0)<0) A-=tmp;
ans=A*B;
for (int i=1;i<n;i++)
{
Y=P[i]; X=P[i+1];
while (dcmp(Dist(X,Y,P[L1]),Dist(X,Y,P[L1%n+1]))<0)
L1=L1%n+1;
while (dcmp(Dot(Y,P[L2%n+1],X)/Dist(X,Y),Dot(Y,P[L2],X)/Dist(X,Y))<0)
L2=L2%n+1;
while (dcmp(Dot(X,P[L3%n+1],Y)/Dist(X,Y),Dot(X,P[L3],Y)/Dist(X,Y))<0)
L3=L3%n+1;
B=Dist(X,Y,P[L1]);
A=Dist(X,Y);
tmp=Dot(Y,P[L2],X)/Dist(X,Y);
if (dcmp(tmp,0.0)<0) A-=tmp;
tmp=Dot(X,P[L3],Y)/Dist(X,Y);
if (dcmp(tmp,0.0)<0) A-=tmp;
ans=min(ans,A*B);
}
printf("%.4lf\n",(double)ans);
cl(P); cl(H); cnt=0; cl(s);
}
return 0;
}

#### BZOJ 1185 [HNOI2007]最小矩形覆盖 旋转卡壳

2015-09-09 18:23:43

#### [BZOJ1185][HNOI2007]最小矩形覆盖（旋转卡壳）

2017-03-20 17:06:05

#### 【BZOJ1185】最小矩形覆盖 计算几何 凸包 旋转卡壳

2016-04-15 22:08:34

#### UVA 10173 Smallest Bounding Rectangle(旋转卡壳求最小面积外接矩形)

2011-06-15 22:13:00

#### UVa 10173 - Smallest Bounding Rectangle

2013-10-12 15:53:34

#### Smallest Bounding Rectangle - uva10173

2015-12-05 18:07:53

#### bzoj 1185: [HNOI2007]最小矩形覆盖 旋转卡壳

2016-04-14 10:21:33

#### BZOJ 1185 HNOI2007 最小矩形覆盖 旋转卡壳

2015-01-23 15:20:18

#### 【BZOJ 1185】[HNOI2007]最小矩形覆盖 旋转卡壳

2017-02-04 21:27:47

#### bzoj 1185: [HNOI2007]最小矩形覆盖 （旋转卡壳）

2017-01-05 09:44:42

## 不良信息举报

[旋转卡壳] BZOJ 1185 [HNOI2007]最小矩形覆盖 && 2218 Uva10173 Smallest Bounding Rectangle