题目大意:给定一个点集,任选四点构成一个凸多边形,求面积最大的凸多边形
枚举四边形的对角线,每次固定一个点,扫对角线上的另一个点
每次找到对角线两侧离对角线最远的点,由于两边的点的移动是单调的,因此可以用旋转卡壳维护
此外四边形的面积用对角线叉积的绝对值除以2就可以算出来了- -
#include <cmath> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define M 2020 #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; } }points[M]; int n,r,h; double ans; Point *q[M<<1]; 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++) q[++r]=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--) q[++r]=stack[i]; } void Rotating_Calipers() { int i; Point **p1,**p2,**p3,**p4; for(i=r;i;i--,q[++r]=q[++h]) { p1=&q[h+1]; p2=p1+2; p3=p1+1; p4=p2+1; for(q[r+1]=q[h+1];p2-q<r;p2++) { while( (**(p3+1)-**p3)*(**p2-**p1)<EPS ) p3++; while( (**(p4+1)-**p4)*(**p1-**p2)<EPS ) p4++; ans=max(ans,(**p4-**p3)*(**p2-**p1)/2); } } } 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("%.3lf\n",ans); return 0; }
BZOJ 1069 SCOI2007 最大土地面积 旋转卡壳
原文地址:http://blog.csdn.net/popoqqq/article/details/43053925