[凸包] BZOJ1069: [SCOI2007]最大土地面积

来源:互联网 发布:淘宝店铺打印快递单 编辑:程序博客网 时间:2024/06/05 06:23

题意

在某块平面土地上有N个点,你可以选择其中的任意四个点,将这片土地围起来,当然,你希望这四个点围成的多边形面积最大。
n<=2000

题解

容易想到凸包。
最优的四边形的端点是落在凸包上的,然后n2枚举对角线。在对角线两侧类似旋转卡壳,利用单调性推得最大三角形。这样就是O(n2)的。
凸包是三角形?不知道啊反正没管就过了……之后才在discuss上看到,可能选凸包上3点,枚举第4个点可以..吧….

#include<cstdio>#include<cmath>#include<algorithm>using namespace std;const int maxn=2005;struct Point{    double x,y;    Point(double t1=0,double t2=0){ x=t1; y=t2; }    bool operator < (const Point &b)const{        if(x<b.x) return true;        if(x>b.x) return false;        return y<b.y;    }   } a[maxn],ch[maxn];typedef Point Vector;Vector operator + (Vector A,Vector B){ return Vector(A.x+B.x,A.y+B.y); }Vector operator - (Point A,Point B){ return Vector(A.x-B.x,A.y-B.y); }double Cross(Vector A,Vector B){ return A.x*B.y-A.y*B.x; }int n,m;double ans;int Andrew(){    sort(a+1,a+n+1);    int len=0;    for(int i=1;i<=n;i++){        while(len>1&&Cross(ch[len]-ch[len-1],a[i]-ch[len-1])<0) len--;        ch[++len]=a[i];    }    int k=len;    for(int i=n-1;i>=1;i--){        while(len>k&&Cross(ch[len]-ch[len-1],a[i]-ch[len-1])<0) len--;        ch[++len]=a[i];    }    return len;}int main(){    freopen("bzoj1069.in","r",stdin);    freopen("bzoj1069.out","w",stdout);    scanf("%d",&n);    for(int i=1;i<=n;i++) scanf("%lf%lf",&a[i].x,&a[i].y);    m=Andrew();    for(int i=0;i<=m-1;i++){        int k1=(i+1)%m,k2=(i+3)%m;        for(int j=(i+2)%m;(j+1)%m!=i;j=(j+1)%m){            while(Cross(ch[k1]-ch[i],ch[j]-ch[i])<Cross(ch[(k1+1)%m]-ch[i],ch[j]-ch[i])) k1=(k1+1)%m;            while(Cross(ch[k2]-ch[j],ch[i]-ch[j])<Cross(ch[(k2+1)%m]-ch[j],ch[i]-ch[j])) k2=(k2+1)%m;            ans=max(ans,Cross(ch[k1]-ch[i],ch[j]-ch[i])+Cross(ch[j]-ch[i],ch[k2]-ch[i]));        }    }    printf("%.3lf\n",ans/2);    return 0;}
阅读全文
0 0
原创粉丝点击