zoukankan      html  css  js  c++  java
  • [SCOI2007]最大土地面积

    1069: [SCOI2007]最大土地面积

    Time Limit: 1 Sec  Memory Limit: 128 MB
    Submit: 3998  Solved: 1620
    [Submit][Status][Discuss]

    Description

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

    Input

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

    Output

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

    Sample Input

    5
    0 0
    1 0
    1 1
    0 1
    0.5 0.5

    Sample Output

    1.000

    HINT

    数据范围 n<=2000, |x|,|y|<=100000

    Source

     
    [Submit][Status][Discuss]

    首先我们可以考虑到如果我们取到了一个最大的四边形,那么这个四边形的四个顶点一定是这些点凸包上的点。也就是说,我们需要先求出这些点的凸包。

    那么求出来了之后呢?我们很明显不能暴力求。。。复杂度明显是N^4级别。那么我们应该怎么求呢?考虑四边形性质,可以沿着对角线分成两个三角形,我们只需枚举对角线即可,然后旋转卡壳,求出两边最大三角形的面积求和即可。三角形的面积可以是这个三角形构成平行四边形的面积/2,所以用叉积就可以方便求出。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    #define ll long long
    #define inf 50000000
    #define re register
    #define MAXN 5005
    using namespace std;
    struct node{
        double x,y;
    };
    node a[MAXN],stackk[MAXN];
    double xx,yy;
    int n,top;
    inline int read()
    {
        int x=0,c=1;
        char ch=' ';
        while((ch>'9'||ch<'0')&&ch!='-')ch=getchar();
        while(ch=='-') c*=-1,ch=getchar();
        while(ch<='9'&&ch>='0')x=x*10+ch-'0',ch=getchar();
        return x*c;
    }
    inline bool cmp(node a,node b)
    {
        if(a.y==b.y) return a.x<b.x;
        return a.y<b.y;
    }
    inline double cross(node a,node b,node c)
    {
        return (b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y);
    }
    inline double js(node a,node b)
    {
        return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
    }
    inline bool cmp1(node a,node b)
    {
        int k=cross(stackk[1],a,b);
        if(k>0) return 1;
        else if(k==0) return js(stackk[1],a)<js(stackk[1],b);
        return 0;
    }
    int main()
    {
        n=read();
        for(re int i=1;i<=n;i++)
        scanf("%lf %lf",&a[i].x,&a[i].y);
        sort(a+1,a+n+1,cmp);
        stackk[++top]=a[1];
        sort(a+2,a+n+1,cmp1);
        stackk[++top]=a[2];stackk[++top]=a[3];
        for(re int i=4;i<=n;i++){
            while(top>0&&cross(stackk[top-1],stackk[top],a[i])<=0)
            top--;
            stackk[++top]=a[i];
        }
        stackk[++top]=a[1];
        double ans=0;
        int a,b;
        for(re int x=1;x<=top;x++){
            a=x%top+1;b=(x+2)%top+1;
            for(re int y=x+2;y<=top;y++){
                while(a%top+1!=y&&cross(stackk[x],stackk[a+1],stackk[y])>cross(stackk[x],stackk[a],stackk[y]))
                a=a%top+1;
                while(b%top+1!=x&&cross(stackk[x],stackk[y],stackk[b+1])>cross(stackk[x],stackk[y],stackk[b]))
                b=b%top+1;
                ans=max(cross(stackk[x],stackk[a],stackk[y])+cross(stackk[x],stackk[y],stackk[b]),ans);
            }
        }
        printf("%.3lf",ans/2);
    }
  • 相关阅读:
    数论练习
    AC自动机*
    矩阵乘法*
    概率期望*
    组合数学练习*
    图论升级*
    【终端使用】"su"命令切换用户
    【终端使用】"which"命令可以查看执行命令所在的位置
    【终端使用】"usermod"命令 和 组(包括:主组、附加组)
    Ubuntu 18.04安装 MySQL 8.0+版本的数据库
  • 原文地址:https://www.cnblogs.com/victorique/p/8682242.html
Copyright © 2011-2022 走看看