#旋转卡壳,计算几何#洛谷 3187 [HNOI2007] 最小矩形覆盖
分析
这个矩形的边至少有一条与凸包的边共线,因此,我们对于每个凸包的边,
利用旋转卡壳求出最上点,最左点,最右点,矩形的顶点用投影求出来,垂直的向量来自凸包的边。
求出四个顶点就顺道能把面积求出来了。
代码
#include <iostream>
#include <algorithm>
#include <cassert>
#include <cmath>
#include <iomanip>
using namespace std;
const int N=50011;
typedef long double ld;
struct Point{
ld x,y;
inline Point operator -(const Point &t)const{
return (Point){x-t.x,y-t.y};
}
}a[N],b[N],Botx,Boty,Topx,Topy;
int n,m,o,umost[N],lmost[N],rmost[N]; double ans=1e18;
ld Dis(Point x){return sqrt(x.x*x.x+x.y*x.y);}
ld dj(Point x,Point y){return x.x*y.x+x.y*y.y;}
ld cj(Point x,Point y){return x.x*y.y-x.y*y.x;}
bool cmp(Point x,Point y){
ld t=cj(x-a[1],y-a[1]);
return t>0||(!t&&Dis(x-a[1])<Dis(y-a[1]));
}
void doit(Point x,Point y,Point umx,Point lmx,Point rmx){
ld Len=Dis(y-x),rlen=dj(y-x,rmx-x)/Len/Len,llen=dj(y-x,lmx-x)/Len/Len;
Point boty=(Point){x.x+(y-x).x*rlen,x.y+(y-x).y*rlen};
Point botx=(Point){x.x+(y-x).x*llen,x.y+(y-x).y*llen};
Point Vertical=(Point){(x-y).y,(y-x).x};
ld len=fabs(cj(y-x,umx-x)/Len)/Dis(Vertical);
Point topy=(Point){boty.x+Vertical.x*len,boty.y+Vertical.y*len};
Point topx=(Point){botx.x+Vertical.x*len,botx.y+Vertical.y*len};
if (ans>Dis(boty-botx)*Dis(topy-boty)){
ans=Dis(boty-botx)*Dis(topy-boty);
Botx=botx,Boty=boty,Topx=topx,Topy=topy;
}
}
void rotation(){
if (m<3) assert(0);
b[m+1]=b[1],b[0]=b[m];
for (int i=1,j=2,x=2;i<=m;++i){
while (j%m+1!=i&&cj(b[i]-b[j],b[i+1]-b[j])<=cj(b[i]-b[j+1],b[i+1]-b[j+1])) j=j%m+1;
while (x%m+1!=i&&dj(b[i+1]-b[i],b[x+1]-b[x])>=0) x=x%m+1;
umost[i]=j,rmost[i]=x;
}
for (int i=m,x=m-1;i;--i){
while ((x+m-2)%m+1!=i%m+1&&dj(b[i+1]-b[i],b[x-1]-b[x])<=0) x=(x+m-2)%m+1;
lmost[i]=x;
}
for (int i=1;i<=m;++i) doit(b[i],b[i+1],b[umost[i]],b[lmost[i]],b[rmost[i]]);
}
int main(){
cin>>n,o=1;
for (int i=1;i<=n;++i) cin>>a[i].x>>a[i].y;
for (int i=2;i<=n;++i)
if (a[i].x<a[o].x||(a[i].x==a[o].x&&a[i].y<a[o].y))
o=i;
swap(a[o],a[1]),sort(a+2,a+1+n,cmp);
b[m=1]=a[1];
for (int i=2;i<=n;++i){
while (m>1&&cj(a[i]-b[m-1],b[m]-b[m-1])>=0) --m;
b[++m]=a[i];
}
rotation();
cout<<fixed<<setprecision(10)<<ans<<'\n';
cout<<fixed<<setprecision(10)<<Botx.x<<' '<<Botx.y<<'\n';
cout<<fixed<<setprecision(10)<<Boty.x<<' '<<Boty.y<<'\n';
cout<<fixed<<setprecision(10)<<Topy.x<<' '<<Topy.y<<'\n';
cout<<fixed<<setprecision(10)<<Topx.x<<' '<<Topx.y<<'\n';
return 0;
}

浙公网安备 33010602011771号