bzoj1069 凸包+旋转卡壳

来源:互联网 发布:淘宝售后客服具体工作 编辑:程序博客网 时间:2024/05/24 01:46

问题:在若干个点中取四个点,求围成的四边形的最大面积。
思路:先求个凸包,n^2 枚举对角线,然后旋转卡壳O(1) 更新左右边界即可。

#include <stdio.h>#include <string.h>#include <iostream>#include <algorithm>#include <vector>#include <queue>#include <set>#include <map>#include <string>#include <math.h>#include <stdlib.h>#include <time.h>using namespace std;typedef long long LL;const int INF=0x7fffffff;const int N =2e3+10;int n,m,k;const double esp =1e-6;int sgn(double x){return x<-esp?-1:x>esp;}struct Point{    void in(){scanf("%lf%lf",&x,&y);}    double x,y;    Point(){}    Point(double x,double y):x(x),y(y){}    Point operator + (Point o){return Point(x+o.x,y+o.y);}    Point operator - (Point o){return Point(x-o.x,y-o.y);}    Point operator * (double len){return Point(x*len,y*len);}    double operator * (Point o){return x*o.y-y*o.x;}    double operator / (Point o){return x*o.x+y*o.y;}    double dis(){return sqrt(x*x+y*y);}    bool operator < (Point o){        if(sgn(y-o.y)==0) return sgn(x-o.x)<0;        return sgn(y-o.y)<0;    }    void out(){        printf("x=%lf,y=%lf\n",x,y);    }}p[N],cv[N];double det(Point a,Point b,Point c){    return (b-a)*(c-a);}double dot(Point a,Point b,Point c){    return (b-a)/(c-a);}Point rot(Point p,double a){    return Point(cos(a)*p.x-sin(a)*p.y,sin(a)*p.x+cos(a)*p.y);}const double pi = acos(-1.0);bool cmp(Point a,Point b){    int dir = sgn(det(p[1],a,b));    if(dir==0) return sgn((a-p[1]).dis()-(b-p[1]).dis())<0;    return dir>0;}int Graham(){    for(int i=2;i<=n;i++) if(p[i]<p[1]) swap(p[i],p[1]);    sort(p+2,p+n+1,cmp);    int tot = 2;    cv[1]=p[1],cv[2]=p[2];    p[n+1]=p[1];    for(int i=3;i<=n+1;i++){        while(tot>1 && sgn(det(cv[tot-1],cv[tot],p[i]))<=0) tot--;        cv[++tot]=p[i];    }    return tot-1;}int main(){    //freopen("in.txt","r",stdin);    while(scanf("%d",&n)==1){        for(int i=1;i<=n;i++) p[i].in();        n = Graham();       // for(int i=1;i<=n;i++) cv[i].out();        double res = 0;        for(int i=1;i<=n;i++){            int r = i,l=i;            for(int j=i+1;j<=n;j++){                Point cur = cv[j]-cv[i];                //cur.out();                Point unit = cv[i]+rot(cur,-pi/2);               // unit.out();                while(sgn(dot(cv[i],unit,cv[r])-dot(cv[i],unit,cv[r%n+1]))<=0) r=r%n+1;                while(sgn(dot(cv[i],unit,cv[l])-dot(cv[i],unit,cv[l%n+1]))>=0) l=l%n+1;                double area = fabs(det(cv[i],cv[j],cv[r]))+fabs(det(cv[i],cv[j],cv[l]));               // printf("start=%d,end=%d,l=%d,r=%d,area=%lf\n",i,j,l,r,area);                res=max(res,area);            }        }        res/=2;        printf("%.3lf\n",res);    }    return 0;}
0 0