1. 凸包(Convex Hull)概念
思考:想象墙上有若干个钉子,将一根皮筋扩大到无穷后松开,皮筋会被部分钉子(最外层)撑开围成一片区域,就是一个几何意义上的凸包。
问题描述:给定2D平面内N个点,求一个包围所有点的凸多边形(即凸包)。
2. 核心概念
- to-left test:判断点位于线段的左侧还是右侧;通过向量叉乘实现;
- in-triangle test:判断点位于三角形内部还是外部;三角形各边沿顺/逆时针做3次to-left test;
- in-polygon test:判断点位于凸多边形内部还是外部;针对给定点按顺/逆时针遍历多边形各边做to-left test,点在各边的同侧即点在多边形内部;时间复杂度O(n);
- support-line:即支撑线,多边形外一点与多边形相切的两点所组成的两条边; 如何求得:将该点p与凸包各个极点分别构成线段pvi,检查vi-1和vi+1(前后序顶点)是否都在这条线的同一侧,如果都在同一侧,那这条线段即为一条支撑线。该算法时间复杂度O(n);
- reduction(归约):如果A≤ₚB,那么B的难度至少跟A的难度一样(或者比A要难),即B的算法下界≥A的算法下界; 通过反证法证明:假设问题A的时间复杂度紧确下界为Ω(T(n)),且存在一个归约过程:①任意规模的实例A可在O(n)时间内构造问题B的输入+②给定B的输出,可在O(n)时间内还原出问题A的输出;若假设问题B存在时间复杂度O(T(n))的算法,则A可在o(n)(归约)+ O(T(n))(解 B)+ o(n)(还原) = O(T(n))时间内解决,与A 的 Ω(T(n)) 下界矛盾。

3. 求解凸包极点算法
- 极点算法:平面n个点可以排列组合成C(n,3)个三角形, 遍历所有点,如果点位于任意三角形内部,则该点不是凸包的极点,否则即为凸包上的某个极点,遍历后按顺序连接极点即得凸包。 时间复杂度:O(n4);

- 极边算法:n个点可以排列组合成C(n,2)条边,遍历所有点,如果对于一条边、所有的点都位于这条边的同侧,则这条边为凸包的极边,遍历后按顺序连接极边。 时间复杂度:O(n3);

- 增量式算法:(参考插入排序,按顺序蚕食、找到下一个凸包极点)先通过预处理排序确保每次插入点都在已形成的凸包外部;对已形成的凸包,求解新点(凸包外点)对凸包的支撑线用以更新凸包。 时间复杂度:O(n2);

- jarvis march算法:从当前极点cur出发,维护一个候选点next,形成线段;对剩余点p做to-left test,若p在线段左侧,则不做处理,如果点在线段右侧,则更新搜索点,直至遍历完所有点,此时搜索点即为目标极点。 时间复杂度:O(nh)(其中h为凸包大小即凸包极边数量,该算法每行进一步、搜索出一条极边需要遍历n次)<O(n2);


- graham scan算法: (构造两个栈)先通过预处理按照极角排序形成两个栈;开始遍历:从T栈顶中取出一点,依次将点与S栈顶两个点做to-left测试,如果为TRUE则加入S栈;如果False则将S栈顶的第一个点pop出去,再进行判断,直到T栈为空。 时间复杂度:O(nlogn);



参考资料:清华大学邓俊辉经典计算几何课程。
如有整理错误,敬请指正。
4365

被折叠的 条评论
为什么被折叠?



