zoukankan      html  css  js  c++  java
  • 凸包——求周长、面积

    凸包

    什么是凸包

    在平面图中给定一些点集,去求出一些点:相邻2点的连线能够将所有的点包围起来

    凸包
    凸包

    葛立恒(Graham)扫描法

    1、先找到左下角的点P0(一定在凸包上)
    2、以P0为原点,将其他的点按照极坐标排序,角度小的排在前,若角度相同,距离近的排在前
    3、P0 ,P1 入栈,从P2(第三个点)开始,若P2 在直线P0 P1(p[ i-1 ] p [ i ]) 的左边 ,则P2入栈,否则P1 出栈,一直遍历完后面所有点 (这里就需要向量叉乘来判断点在线的左边还是右边)
    4、最后留在栈中的点就是凸包上的点

    图示
    图示

    撸代码:

    #include<iostream>
    #include<stdio.h>
    #include<math.h>
    #include<algorithm>
    using namespace std;
    struct Point
    {

        int x,y;
    }p[1010];
    int XMUL(Point a,Point b,Point c,Point d)/**ab向量 X cd向量*/
    {
        return ((b.x-a.x)*(d.y-c.y)-(d.x-c.x)*(b.y-a.y));
    }
    double dis(Point a,Point b)
    {
        return sqrt((a.x-b.x)*(a.x-b.x)*1.0+(a.y-b.y)*(a.y-b.y)*1.0);
    }
    bool comp(Point a,Point b)
    {
        int m=XMUL(p[0],a,p[0],b);
        if(m>0)
            return 1;
        else if(m==0&&dis(p[0],a)-dis(p[0],b)<1e-8)
            return 1;
        return 0;
    }
    int main()
    {
        int n,r;
        while(~scanf("%d%d",&n,&r))
        {
            for(int i=0;i<n;i++)
                scanf("%d%d",&p[i].x,&p[i].y);
            /**找到P0*/
            int k=0;
            for(int i=1;i<n;i++)
            {
                if(p[k].y>p[i].y)
                    k=i;
                else if(p[k].y==p[i].y&&p[k].x>p[i].x)
                    k=i;
            }
            swap(p[k],p[0]);
            /**按照极角坐标排序*/
            sort(p+1,p+n,comp);

            Point s[1010];
            int top=1;
            s[0]=p[0];
            s[1]=p[1];
            for(int i=2;i<n;i++)
            {
                while(top>=1&&XMUL(s[top-1],s[top],s[top],p[i])<0)
                    top--;
                s[++top]=p[i];
            }
            double ans=0;
            for(int i=0;i<top;i++)
                ans+=dis(s[i],s[i+1]);
            ans+=dis(s[top],s[0]);
            double PI = acos(-1);
            ans+=2*PI*r;
            printf("%.0f ",ans);
        }
        return 0;
    }

    若要求凸包的面积

    还是先求出凸包上的点,再根据三角形面积公式(叉乘计算)

            /**求凸包面积,{1/2*a*b*sin(c)} ==a,b两向量叉乘 */
            int area=0;
            for(int i=1;i<top;i++)
            {
                area+=cross(s[0],s[i],s[i+1]);
            }
            area=abs(area)/2;
  • 相关阅读:
    Spring-cloud微服务 Eureka学习教程-分布式搭建EurekaServer、EurekaClient(中级)
    Eureka与ZooKeeper 的比较
    使用git将项目上传到github(最简单方法)
    Spring-cloud微服务 Eureka学习教程-单服务器配置之快速搭建EurekaServer、EurekaClient(基础)
    连接数据库报错:1130-Host 'xxx' is not allowed to connect to this MySQL server解决
    Sort List
    Insertion Sort List
    LRU Cache
    Binary Tree Postorder Traversal
    Binary Tree Preorder Traversal
  • 原文地址:https://www.cnblogs.com/HappyKnockOnCode/p/12740087.html
Copyright © 2011-2022 走看看