• 《Algorithms算法》笔记:元素排序(4)——凸包问题


    《Algorithms算法》笔记:元素排序(4)——凸包问题


    凸包问题

    凸包问题就是说,找到一个最小的凸多边形能圈住所有的点。

    这里写图片描述

    凸包问题的应用

    • 运动规划:找到从s到t的最短路径,最短路径肯定在凸包上

    这里写图片描述

    • 最远的一对:相隔最远的点对肯定在凸包上

    Alt text

    凸包的几何性质

    • 可以通过逆时针遍历所有凸包顶点
    • 凸包的顶点是关于p的极角的递增序列,而p有最小的y坐标。

    这里写图片描述

    Graham 扫描算法

    1. 选择y坐标最小的p
      • 如何确定最小y坐标?
        循环一遍
    2. 对所有的点按关于p的 极角排序
      • 如何对点进行极角排序?
      • 如何效率的排序?
        用MergeSort
    3. 按顺序连接每个点,如果发现打破pi2pi1pi 打破了逆时针的原则,则舍弃pi1,pi

      • 如何判断是否打破了逆时针原则ccw?
      • 如何解决退化问题(多个点在一条直线上)

        通过计算(b-a)和(c-a)的叉乘就行了。
        如果area > 0 则是逆时针,
        如果area < 0 则是顺时针
        如果area = 0 则是共线

    这里写图片描述

    代码

    由于每次要判断最后的2个点是否是逆时针,毫无疑问使用栈结构是比较合适的

    public class Point2D 
    {
       private final double x;
       private final double y;
       public Point2D(double x, double y)
       {
          this.x = x;
          this.y = y;
       } 
       ...
       public static int ccw(Point2D a, Point2D b, Point2D c)
       {
          double area2 = (b.x-a.x)*(c.y-a.y) - (b.y-a.y)*(c.x-a.x);
          if      (area2 < 0) return -1;  
    // clockwise
          else if (area2 > 0) return +1;  
    // counter-clockwise
          else                return  0;  
    // collinear
       }
    }
    stack<Point2D> hull = new Stack<Point>();
    Array.sort(p,Point2D.Y_ORDER);//find p
    Array.sort(p,p[0],BY_POLAR_ORDER)//
    
    hull.push(p[0]);
    hull.push(p[1]);
    
    for(i = 2;i < N;i++)
    {
        Point2D top = hull.pop();
        while(Point2D.ccw(hull.peek(),top,p[i]) <= 0)
            top = hull.pop();
        hull.push(top);
        hull.push(p[i]);
    
    }
  • 相关阅读:
    Laravel 学习笔记之文件上传
    Composer学习
    Laravel 学习笔记之数据库操作——Eloquent ORM
    PHP至Document类操作 xml 文件
    使用promise构建一个向服务器异步数据请求
    遍历DOM树
    关于tp验证码模块
    layui 封装自定义模块
    js进阶之路,关于UI资源的优化(转载)
    关于js 重载
  • 原文地址:https://www.cnblogs.com/voidsky/p/5373921.html
Copyright © 2020-2023  润新知