ccz181078

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: :: 管理 ::

Description

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

Input

  第1行一个正整数N,接下来N行,每行2个数x,y,表示该点的横坐标和纵坐标。

Output

  最大的多边形面积,答案精确到小数点后3位。

选的点都在凸包上且对角线上的点相距最远,所以可以顺序枚举凸包上的点并旋转卡壳
#include<cstdio>
#include<cmath>
#include<algorithm>
typedef long double ld;
const ld _0=1e-7;
struct vec{ld x,y;};
vec operator+(vec a,vec b){return (vec){a.x+b.x,a.y+b.y};}
vec operator-(vec a,vec b){return (vec){a.x-b.x,a.y-b.y};}
vec operator*(vec a,ld x){return (vec){a.x*x,a.y*x};}
ld operator*(vec a,vec b){return a.x*b.y-a.y*b.x;}
bool operator<(vec a,vec b){return a*b>0;}
ld abs(vec a){return sqrt(a.x*a.x+a.y*a.y);}
int n,p,p1,p2,p3;
vec vs[10010],ps[20010],m;
ld ans=0;
int main(){
    scanf("%d",&n);
    for(int i=0;i<n;i++){
        double x,y;
        scanf("%lf%lf",&x,&y);
        vs[i]=(vec){x,y};
    }
    for(int i=1;i<n;i++)if(vs[i].x<vs[p].x||vs[i].x==vs[p].x&&vs[i].y<vs[p].y)p=i;
    m=vs[p];
    for(int i=0;i<n;i++){
        vs[i]=vs[i]-m;
        if(abs(vs[i])<_0)vs[i--]=vs[--n];
    }
    std::sort(vs,vs+n);
    ps[0]=(vec){0,0};
    ps[p=1]=vs[0];
    for(int i=1;i<n;i++){
        while(p&&(ps[p]-ps[p-1])*(vs[i]-ps[p])<_0)--p;
        ps[++p]=vs[i];
    }
    n=p+1;
    for(int i=0;i<=n;i++)ps[i+n]=ps[i];
    int n0=n;
    n=n*2+1;
    for(p=0,p1=p2=p3=1;p<n0;p++){
        while(p2<n&&abs(ps[p2+1]-ps[p])>abs(ps[p2]-ps[p]))++p2;
        if(p2>p3)p3=p2;
        vec w=ps[p2]-ps[p];
        while(p1<n&&w*(ps[p1+1]-ps[p])<w*(ps[p1]-ps[p]))++p1;
        while(p3<n&&w*(ps[p3+1]-ps[p])>w*(ps[p3]-ps[p]))++p3;
        ld S=w*(ps[p3]-ps[p1]);
        if(S>ans)ans=S;
    }
    printf("%.3lf\n",(double)ans*.5);
    return 0;
}

 

posted on 2016-06-28 09:10  nul  阅读(347)  评论(0编辑  收藏  举报