zoukankan      html  css  js  c++  java
  • 凸包算法学习笔记

    Graham 算法

    1. 先选一个y最小的点p(y相同选x最小)
    2. 然后将其他点以p为原点进行极角排序
    3. 从p点开始维护一个单调栈,如果栈顶两个元素和新加入点的叉积小于0就弹出。
    Point tbBottom;
    bool cmpTB(Point a,Point b) {//上半平面极角排序;
        double x=xmult(tbBottom,a,b);
        if(sgn(x)>0||(sgn(x)==0&&dist(a,tbBottom)<dist(b,tbBottom))) return 1;//距离近的放前面
        return 0;
    }
    vector<Point> getTB(vector<Point> p){//n>=3
        int n=p.size();
        int minp=0;
        for(int i=1;i<n;i++){
            if(sgn(p[i].y-p[minp].y)==-1 || (sgn(p[i].y-p[minp].y)==0&&sgn(p[i].x-p[minp].x)==-1)){//选左下角的第一个点
                minp=i;
            }
        }
        swap(p[0],p[minp]);//使第一个点y最小
        tbBottom=p[0];
        sort(p.begin()+1,p.end(),cmpTB);
        vector<Point>tb;
        tb.push_back(p[0]);
        tb.push_back(p[1]);
        for(int i=2;i<n;i++){
            while(tb.size()>=2 && sgn(xmult(tb[tb.size()-2],tb[tb.size()-1],p[i]))<=0){
                tb.pop_back();
            }
            tb.push_back(p[i]);
        }
        return tb;
    }
    

    Andrew算法

    1. 将所有点按x第一关键字,y第二关键字从小到大排序。
    2. 从最左边的点开始向右遍历点并维护单调栈,如果栈顶两个元素和新点的叉积<0则弹出,这样会形成一个下凸包
    3. 同样的从右往左继续维护单调栈,形成上凸包
    bool cmpA(Point a,Point b){
        return a.x<b.x||(a.x==b.x && a.y<b.y);
    }
    vector<Point> Andrew(vector<Point> p) { //Andrew算法求凸包(求上链与下链):p是点数组,ch是凸包顶点,返回顶点数
        //输入不能有重复点,若要凸包边上没有输入点,将两个<=改为<
        sort(p.begin(),p.end(),cmpA);
        vector<Point>tb;
        for(int i=0; i<p.size(); i++) {//Cross(ans[top-1]-ans[top-2],p[i]-ans[top-2])
            while(tb.size()>=2&&sgn(xmult(tb[tb.size()-2],tb[tb.size()-1],p[i]))<=0)tb.pop_back();
            tb.push_back(p[i]);
        }
        int temp=tb.size();
        for(int i=p.size()-2; i>=0; i--) {
            while(tb.size()>temp&&sgn(xmult(tb[tb.size()-2],tb[tb.size()-1],p[i]))<=0)tb.pop_back();
            tb.push_back(p[i]);
        }
        if(p.size()>1)tb.pop_back();
        return tb;
    }
    

    总结

    Andrew算法代码更短,排序更快(比较时不需要计算叉积),而且Andrew算法不容易出现精度产生的误差问题(这个很重要)。从各方面来看都是Andrew算法更优

  • 相关阅读:
    [转]tesseract api C++使用例子
    Flyway记录
    线程安全性和共享
    并发初解
    生产环境中遇到过什么问题?或者有没有自己解决什么问题比较自豪的
    Java白皮书关键词理解【随记】
    技术面试记录
    Mac下完全卸载IntelliJIdea
    docker提交镜像后运行新容器mysql无法启动
    IntelliJ IDEA切换SDK解决卡顿的问题
  • 原文地址:https://www.cnblogs.com/ucprer/p/14548010.html
Copyright © 2011-2022 走看看