• poj1113--凸包(Andrew)


    题目大意:

          给出平面上若干个点的坐标,你的任务是建一个环形围墙,把所有的点围在里面,且距所有点的距离不小于l。求围墙的最小长度。

    思路:

    很容易得出答案就是凸包周长+以l为半径的圆的周长。

    这里讲一下Andrew算法。

    Andrew是Graham算法的变种,而且Andrew更快,更稳定。

    Andrew算法思想是先将n个点按照x坐标从小到大排序(x相同按照y从小到大),得到一个序列a1,a2,...an,将a1,a2放入ch数组,从a3开始,判断点是否在凸包当前前进方向的左边,如果是,就将点加入ch数组,否则就删除ch中的点直到在左边为止,重复上述操作。值得注意的是,Andrew需要做2次上述过程,第一次求出“下凸包”,第二次求出“上凸包”,合并起来就是完整的凸包。

    具体看代码。

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    #define pi acos(-1.0)
    struct point{
        int x,y;
        point(int x=0,int y=0):x(x),y(y){}
    }a[1001],ch[1001];
    typedef point Vector;
    point operator - (point a,point b){
        return point(a.x-b.x,a.y-b.y);
    }
    int cross(Vector a,Vector b){
        return(a.x*b.y-a.y*b.x);
    }
    double length(Vector a){
        return(sqrt((double)a.x*a.x+a.y*a.y));
    }
    bool cmp(point a,point b){
        return(a.x<b.x||(a.x==b.x&&a.y<b.y));
    }
    int n,i,j,k,l,x,y;
    double sum=0;
    int main(){
        scanf("%d%d",&n,&l);
        for(i=1;i<=n;++i)scanf("%d%d",&a[i].x,&a[i].y);
        sort(a+1,a+n+1,cmp);
        int m=0;
        for(i=1;i<=n;++i){
            while(m>1&&cross(ch[m]-ch[m-1],a[i]-ch[m-1])<0)m--;
            ch[++m]=a[i];
        }
        k=m;
        for(i=n-1;i>=1;--i){
            while(m>k&&cross(ch[m]-ch[m-1],a[i]-ch[m-1])<=0)m--;
            ch[++m]=a[i];
        }
        for(i=1;i<m;++i)sum+=length(ch[i+1]-ch[i]);
        printf("%.0f
    ",sum+2*pi*l);
        return 0;
    }
    poj1113
  • 相关阅读:
    ASCII码详解
    C#中判断上传类型为Excel,03和07版的链接字符串
    文本搜索工具的制作过程之搜索
    文本搜索工具之显示
    用C#实现十六进制字符串转换为ASCII
    7个秘诀 工作效率和薪水都翻倍
    C#委托
    VB的写法,关于版本写入注册表
    k8s 集群灾难恢复 k8s
    k8s 接合阿里云负载均衡 k8s
  • 原文地址:https://www.cnblogs.com/gjghfd/p/5634903.html
Copyright © 2020-2023  润新知