题目大意:最小矩形覆盖
首先有一个结论:凸包上一定有一条边与矩形的一条边重合
证明:如果不存在一条边与矩形的一条边重合,那么我将这个矩形旋转一下一定会比之前更小
于是我们枚举其中一条边,对其余三个点卡壳即可
这旋转卡壳写的真叫一个卡壳- - 还好1A掉了- -
#include <cmath> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define M 50500 #define EPS 1e-7 using namespace std; struct Point{ double x,y; Point() {} Point(double _,double __): x(_),y(__) {} friend istream& operator >> (istream &_,Point &p) { scanf("%lf%lf",&p.x,&p.y); return _; } bool operator < (const Point &p) const { if(fabs(x-p.x)<EPS) return y<p.y; return x<p.x; } Point operator + (const Point &p) const { return Point(x+p.x,y+p.y); } Point operator - (const Point &p) const { return Point(x-p.x,y-p.y); } double operator * (const Point &p) const { return x*p.y-y*p.x; } Point operator * (const double &rate) const { return Point(x*rate,y*rate); } friend ostream& operator << (ostream& _,const Point &p) { printf("%.5lf %.5lf",p.x,p.y); return _; } }points[M]; struct Line{ Point p,v; Line() {} Line(const Point &_,const Point &__): p(_),v(__) {} }; int n,top; double ans=1e15; Point ans_points[4]; Point *stack[M<<1]; Point Get_Intersection(const Line &l1,const Line &l2) { Point u=l1.p-l2.p; double temp=(l2.v*u)/(l1.v*l2.v); return l1.p+l1.v*temp; } void Get_Convex_Hull() { static Point *stack[M]; int i,top=0; for(i=1;i<=n;i++) { while( top>=2 && (*stack[top]-*stack[top-1])*(points[i]-*stack[top])>=-EPS ) stack[top--]=0x0; stack[++top]=&points[i]; } for(i=1;i<=top;i++) ::stack[++::top]=stack[i]; top=0; for(i=1;i<=n;i++) { while( top>=2 && (*stack[top]-*stack[top-1])*(points[i]-*stack[top])<=EPS ) stack[top--]=0x0; stack[++top]=&points[i]; } for(i=top-1;i>1;i--) ::stack[++::top]=stack[i]; int limit=::top; for(i=1;i<=limit;i++) ::stack[++::top]=::stack[i]; ::stack[++::top]=::stack[1]; } void Rotating_Calipers() { int limit=top>>1; Point **p1,**p2,**p3,**p4; p1=stack+1; Point v1=(**(p1+1)-**p1); Point v2(v1.y,-v1.x); Point v3(v2.y,-v2.x); Point v4(v3.y,-v3.x); for(p2=p1;(**(p2+1)-**p2)*v2<0;p2++); for(p3=p2;(**(p3+1)-**p3)*v3<0;p3++); for(p4=p3;(**(p4+1)-**p4)*v4<0;p4++); for(;p1<=stack+limit;p1++) { v1=(**(p1+1)-**p1); v2=Point(v1.y,-v1.x); v3=Point(v2.y,-v2.x); v4=Point(v3.y,-v3.x); for(;(**(p2+1)-**p2)*v2<0;p2++); for(;(**(p3+1)-**p3)*v3<0;p3++); for(;(**(p4+1)-**p4)*v4<0;p4++); Point temp_points[4]; Line l1(**p1,v1); Line l2(**p2,v2); Line l3(**p3,v3); Line l4(**p4,v4); temp_points[0]=Get_Intersection(l1,l4); temp_points[1]=Get_Intersection(l4,l3); temp_points[2]=Get_Intersection(l3,l2); temp_points[3]=Get_Intersection(l2,l1); double area=(temp_points[1]-temp_points[0])*(temp_points[3]-temp_points[0]); if(area<ans) memcpy(ans_points,temp_points,sizeof ans_points),ans=area; } } int main() { int i; cin>>n; for(i=1;i<=n;i++) cin>>points[i]; sort(points+1,points+n+1); Get_Convex_Hull(); Rotating_Calipers(); printf("%.5lf\n",ans); int st=0; for(i=1;i<4;i++) if( ans_points[i].y<ans_points[st].y || fabs(ans_points[i].y-ans_points[st].y)<EPS && ans_points[i].x<ans_points[st].x ) st=i; for(i=0;i<4;i++) cout<<ans_points[i+st&3]<<endl; return 0; }
BZOJ 1185 HNOI2007 最小矩形覆盖 旋转卡壳
原文地址:http://blog.csdn.net/popoqqq/article/details/43056349