zoukankan      html  css  js  c++  java
  • HDU1348--Wall(凸包)

    佷裸的一道凸包题,就是多组数据,每组给你点数和圆的半径,然后一堆坐标,最后输出圆的周长加上这个最小凸包的周长。

    这里我用的是Graham_scan方法,具体的就是:

    1.我们取Y坐标最小的点A作为原点建立平面直角坐标系,然后以剩余点与X轴的夹角从小到大逆时针依次标记,可以不难发现A,B必在这个最小凸包上

    2.然后按照字母顺序连接,首先连接AB,然后是BC,我们发现∠ABC是小于180°的,所以我们暂且认为C是在这个最小凸包上的

    3.现在,我们继续连接CD,但此时GG的事就是我们发现∠BCD为大约180°的角如果我们认为D也是凸包上的点,这里就会出现一个凹陷,因此我们既要保证C、D都在凸包内,又要不出现凹陷,只能去掉BC而选BD

    4.以此类推,不难发现我们的最小凸包应该长这个样子

    5.最后,用两点距离公式来求出周长即可

    Q:如何判断夹角是否为凸凹?

    我们用叉乘来判断

     这里的左边即为小于180°,右边为大于180°(可以画图证明)

    这样就可以判断了。

    丑陋的代码(这道题别忘加上2πr):

    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    const int  maxn=1010;
    const double Pi=acos(-1.0);
    struct Node
    {
        double x,y;
    }p[maxn],P[maxn];
    int n,tot;
    double ans,l;
    double X(Node A,Node B,Node C)
    {
        return (B.x-A.x)*(C.y-A.y)-(C.x-A.x)*(B.y-A.y);
        
    }//叉乘 
    double len(Node A ,Node B)
    {
        return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));
    }//距离 
    bool cmp(Node A,Node B)
    {
        double pp=X(p[0],A,B);
        if(pp>0) return true;
        if(pp<0) return false;
        return len(p[0],A)<len(p[0],B); 
    }//按夹角逆时针排序 
    int main()
    {
        int t;
        scanf("%d",&t);
        for(int u=1;u<=t;u++)
        {
            if(u!=1)printf("
    ");
            scanf("%d%lf",&n,&l);
            ans=2*Pi*l;
            for(int i=0;i<n;i++)
            scanf("%lf%lf",&p[i].x,&p[i].y);
            if(n==1)
            {
                printf("%.0f
    ",ans);
            }
            else if(n==2)
            {
                printf("%.0f
    ",ans+len(p[0],p[1]));
    
            }
            else 
            {
                for(int i=0;i<n;i++)
                {
                    if(p[i].y<p[0].y)
                    {
                        swap(p[i],p[0]);
                    }
                    else if(p[i].y==p[0].y&&p[i].x<p[0].x)
                    {
                        swap(p[i],p[0]);
                    }
                }
                sort(p+1,p+n,cmp);
                P[0]=p[0];
                P[1]=p[1];
                tot=1;
                for(int i=2;i<n;i++)
                {
                    while(tot>0&&X(P[tot-1],P[tot],p[i])<=0)
                    tot--;
                    tot++;
                    P[tot]=p[i];
                }
                for(int i=0;i<tot;i++)
                ans+=len(P[i],P[i+1]);
                ans+=len(P[0],P[tot]);
                printf("%.0f
    ",ans); 
            }
        }
        return 0;
    } 

    感觉说的应该是不太好,有什么错误请指出,谢谢

  • 相关阅读:
    查看hbase中的中文
    查看hbase中的中文
    scala使用hbase新api
    scala使用hbase新api
    IDEA15使用maven编译scala和java
    IDEA15使用maven编译scala和java
    IDEA非sbt下spark开发
    IDEA非sbt下spark开发
    sed初学者实用说明
    sed初学者实用说明
  • 原文地址:https://www.cnblogs.com/ninelifecat/p/10333000.html
Copyright © 2011-2022 走看看