zoukankan      html  css  js  c++  java
  • 计算几何经典算法凸包

      在学习了一些有关计算机几何的基础知识和一些基本工具之后要快速的解决一些简单的几何问题,如两点之间的距离、两线段的交点个数等等是可以轻松应付的,但是对于复杂点的几何问题,我们还是要有更好的算法,这样才可以更高效的解决它。在这一篇中来总结 平面凸包 的 Graham算法;http://www.cnblogs.com/jbelial/

    平面凸包 :

     定义: 对一个简单多边形来说,如果给定其边界上或内部的任意两个点,连接这两个点的线段上的所有点都被包含在该多边形的边界上或内部的话,则该多边形为凸多边形 。

    在解决平面凸包下面介绍了两种算法:

    一、  Graham扫描法,运行时间为O(nlgn)

    二、  Jarvis步进法,运行时间为O(nh),h为凸包中的顶点数。

    例题 1
     1 问题描述1:
    2 求覆盖平面上n 个点的最小的凸多边形。也可以这样描述:给定一个连接的多边形,可能是凸多边形,也有可能是凹多边形。现在,你的任务就是编程求这个多边形的最小凸包。如果它本身是凸多边形,那么最小凸包就是它本身。
    3 数据范围:
    4 多边形顶点坐标X,Y 是非负整数,不超过512。
    5 输入:
    6 共有K 组数据,每组测试数据的点都是按逆时针顺序输入的,没有3 个点共线。
    7 每组测试数据的第1 行是N,表示有N 个点。以下N 行,每行两个整数X,Y。
    8 输出:
    9 输出格式与输入格式一样,第一行是K,表示共有K 组输出。以下K 组数据:
    10 每组的第一行为M,表示该凸包上有M 个顶点,以下M 行每行两个整数X,Y,表示凸包顶点的坐标。也按逆时针方向输出。
    11 样例输入:
    12 1
    13 14
    14 30 30
    15 50 60
    16 60 20
    17 70 45
    18 86 39
    19 112 60
    20 200 113
    21 250 50
    22 300 200
    23 130 240
    24 76 150
    25 47 76
    26 36 40
    27 33 35
    28 样例输出:
    29 1
    30 8
    31 60 20
    32 250 50
    33 300 200
    34 130 240
    35 76 150
    36 47 76
    37 30 30

      

                                                                                                                

    Graham扫描法

       基本思想:通过设置一个关于候选点的堆栈s来解决凸包问题。

       操作:输入集合Q中的每一个点都被压入栈一次,非CHQ(表示Q的凸包)中的顶点的点最终将被弹出堆栈,当算法终止时,堆栈S中仅包含CH(Q)中的顶点,其顺序为个各顶点在边界上出现的逆时针方向排列的顺序。

    注:下列过程要求|Q|>=3,它调用函数TOPS)返回处于堆栈S 顶部的点,并调用函数NEXT-TO TOPS)返回处于堆栈顶部下面的那个点。但不改变堆栈的结构。

    GRAHAM-SCAN(Q)

    1           P0 Q Y 坐标最小的点,如果有多个这样的点则取最左边的点作为P0

    2           <P1,P2,……,Pm>Q 中剩余的点,对其按逆时针方向相对P0 的极角进行排序,如果有数个点有相同的极角,则去掉其余的点,只留下一个与P0 距离最远的那个点;

    3           PUSH(p0 , S)

    4           PUSH(p1 , S)

    5           PUSH(p3 , S)

    6           for i 3 to m

    7               do while 由点NEXT-TOP-TOPS),TOPS)和Pi 所形成的角形成一次非左转

    8                   do POP(S)

    9               PUSH(pi , S)

    10        return S

     

    首先,找一个凸包上的点,把这个点放到第一个点的位置P0。然后把P1~Pm 按照P0Pi的方向排序,可以用矢量积(叉积)判定

    做好了预处理后开始对堆栈中的点<p3,p4,...,pm>中的每一个点进行迭代,在第78行的while循环把发现不是凸包中的顶点的点从堆栈中移去。(原理:沿逆时针方向通过凸包时,在每个顶点处应该向左转。因此,while循环每次发现在一个顶点处没有向左转时,就把该顶点从堆栈中弹出。)当算法向点pi推进、在已经弹出所有非左转的顶点后,就把pi压入堆栈中。

    举例如下:

                               

                                     

                               

                                    

                                     

                                                             

    练习:HDU 1392 Surround the Trees

    模板:http://www.cnblogs.com/jbelial/archive/2011/08/05/2128624.html

  • 相关阅读:
    Python爬虫之selenium各种注意报错
    以后的路还很长
    巧学DBhelper
    怎么学习程序语言
    C# winform 实现图片轮播
    P6477 [NOI Online #2 提高组]子序列问题(民间数据) 题解
    NOI Online Round 2 TG 游记
    「EZEC」 Round1 开学信心赛 游记
    P6023 走路 题解
    P6022 快乐水 题解
  • 原文地址:https://www.cnblogs.com/jbelial/p/2128625.html
Copyright © 2011-2022 走看看