CG2017 PA5-2 FruitNinja(水果忍者)· 下
招募告示:想做一个苏菲2炼金的网站,用于计算最优/次优合成图,涉及算法、Web开发、UI/UX等等,有兴趣请私我哒~
2. 思路分析
2.3 Linear Programming
根据上一节的思路,我们只需要在对偶空间里面求解Half-plane Intersection即可,但是我们需要注意一下题目所需要求解的问题:题目需要我们求解是否有解,而不是整个空间解集。也就说我们可以把求解整个空间解集转换成求其中一个解,只要有一个解,我们就能回答题目有没有的问题,也能简化求解的复杂度。
因为原先我们是求解空间平面,现在我们只是求解一个点,大大降低算法难度。依据这个思路,我们直接使用教材上面的Linear Programming(LP)就可以解决问题。这个方法非常的直接,这里使用教材上面的图例1简要说明一下,大家就能看图理解啦哒:

但是这个方法有较高的数学浓度!Linear Programming具体有两种求解方法:1)有界LP 或 2)无界LP;前者需要根据实际问题确定角点,后者需要先判断一个矢量→d,判别方法教材中有涉及,但笔者数学功力不太行,实在无法理解,所以也无法实现这个解法。但是这个方法是本题的最优解,根据教材上面的定理:
〖定理4.10〗1
即使是在最坏情况下,使用不超过线性规模的空间,也可以在O(n)的随机期望运行时间内,对包含n 个约束条件的任何二维线性规划问题进行求解。
我们可以得到这个方法的时间和空间复杂度都为O( 2n ),因为最多有2n个端点,也即有线性数量的半平面,所以这个解法为理论上的最快算法。因为没有实现,所以这里笔者把实现细节的分享放在后一种方法,直接求解整个解集空间:Half-plane Intersection。如有童鞋成功实现这个方法,请务必联系我拜膜一下哇~
2.4 Half-plane Intersection
2.4.1 整体思路
Half-plane Intersection算法是基于 Map Overlay,所以在阅读下面内容之前,大家需要理解Map Overla算法。Half-plane Intersection算法非常的直接,使用的是Divide-and-Conquer(分治)进行计算,每次递归返回时,我们需要使用MapOverlay来计算半平面的交集(这个交集必为Covexll),但这个交集和之前的MapOverlay不太一样,这里的交集结果可能是平面,线段,或者是点。
而且实现起来最为棘手的问题是,半平面理论上是一个无限大的平面,而MapOverlay处理的是有限的平面。笔者尝试直接使用半平面来求解,但实在是太复杂,最后遂放弃。之后只能祭出计算几何里面的一个”大杀器“:无限化有限,即我们最开始用一个Bounding box把所有半平面转换成有限的平面,然后再用MapOverlay进行求解即可:

和CG2017 PA1-2 Crossroad (十字路口)处理思路类似,但是这样也会遇到一个相同的问题:我们怎么选定一个足够大的 Bounding Box 能覆盖所有的半平面的相交区域呢?笔者想了半天只能先找出所有半平面的交点,然后用一个能覆盖所有交点的 Box 来进行计算,但是这样又会有一个问题:我们如何在O( nlogn )时间内求得相当于n条直线的交点呢?而且这个方法还不能覆盖没有交点的情况,即所有半平面所在的直线都是平行的。所以这个问题也是一个实际实现之中遇到的难度,最后的解决方法是用一个数值很大的 Box 来进行求解,虽然能满足题目上面的数据集,但在理论上还是有缺陷。如果大家对此有比较好的思路,欢迎讨论哒~
解决了半平面的无限化问题,接下来就是如何进行求交计算了。总的来说,笔者总结了Haff-plane Intersection之中所涉及的相交情况,因为相交结果只有四种:有限平面,线段,点,空集。那么我们需要考虑的相交情况,就是上述四种结果的排列组合。这里我们简要说明一下每种情况的求解方法:
- 点 & 点:只需要判断两个点是否重合,重合则有解,且解为点;如果不重合,则解为空;
- 点 & 线段:只需判断点是否在线段上面,在则解为点;如果不在,则解为空;
- 点 & 面:只需判断点是否在面之中(或边界上),在则解为点;如果不在,则解为空;
- 线段 & 线段:线段稍微复杂一些,解可能为点,线段;
- 线段 & 面:同样解可能为点,线段;
- 面 & 面:使用MapOverlay求解即可,再查看两个平面是否有相交的面,有则输出该面,如果相交于一点,则解为点,如果相交为线段,则解为线段;
- 空集 & ( 点 | 线段 | 面 | 空集 ) :只要有一个为空,结果必为空集;
有限平面相交,笔者在MapOverlay里面已经进行过详细介绍,这里就不再赘述,所以我们把重点放在4)和 5)上面,而且两者有相似的地方。
2.4.2 线段和面的相交
首先,我们先来看看线段 & 线段求交结果的所有情况:(注意这里不是一般的线段求交,解可能为线段)

我们可以观察到,两条线段1)如果没有交点,则解为空;2)如果有一个交点,则解为交点;3)如果有两个交点,则解为两个交点组成的线段。通过这个观察,我们可以使用Segment Intersection算法进行求解,根据交点的数目来求得具体的解。但是,这里用到的Segment Intersection算法需要报告重合线段的交点,但之前一般意义上来说,这种不算相交,但这里需要报告出来,需要大家注意。
接下来,我们来看看线段和面相交的所有情况:

和线段 & 线段类似,我们还是先通过交点的数目来进行判断,但情况会复杂很多:
- 如果没有交点,且两个端点都不在平面内,则解为空;但如果两个端点都在平面内,则解为线段;
- 如果有一个交点,且有一端端点在平面内部,则解为交点后在平面内部端点所组成的线段;如果没有端点落在平面内,则解为交点;
- 如果有两个交点,则解为两个交点组成的线段;
所以我们可以先把平面转换成线段(组成平面的线段),然后与给定线段进行Segment Intersection算法求点交,之后再根据上述情况分情况进行讨论即可,但要注意平面线段自己的交点不需要报告。并且图例中我们使用的三角形,但任意凸多边形都有相似的性质。并且根据教材上面的定理:
〖推论4.4〗1
给定平面上的一组共n 张半平面,可以使用线性的空间,在O(nlogn)时间内计算出其公共的交集。
我们可知,这个解法的时间复杂度为O( nlogn ),但说实话,这个解法实现难度超高,因为需要另外两个算法(Segment Intersection & MapOverlay )作为基础算法,才能进行实现,所以不太推荐Half-plane Intersection去解决本题。大家可以看看 2.5 其他解法 中的其他思路。
到此我们讲解完Half-plane Intersection的实现细节,同时在这里我们也全部实现和讲解了 清华计算几何 10个大作业,不知道大家一路看下来,觉得难度如何?是不是既折磨又享受哒?哈哈,也感谢大家一路以来的支持咯,能看到这里真是辛苦了呢~~之后应该会把重心转向找工和个人网站的搭建上面了,再像现在这样无忧无虑的搞研究的机会可能不多了呢。
最后在这里感叹一句哒:这个过程真的是,很开心哦~ 那么,暂时拜拜咯ヾ(•ω•`)o
2.5 其他解法
根据 @IIIustrious 的思路,本题可以利用凸包算法来解决,具体思路如下:
数据点筛选:
数据点存在以下问题,需要经过处理才能使用。
- 有的线段横坐标相同
- 给定线段的纵坐标顺序混乱
- 线段的两个端点同时存储在一个三元组里。
针对以上问题,需要特殊处理数据:
- 同一横坐标有多条直线的,只保留一对端点,下端点取所有下端点中最高的,上端点取所有上端点中最小的
- 在输入时判断两个纵坐标大小,看情况swap一下
- 上点和下点分开存储,放在数组里
求半凸包:
需要求上下端点的半凸包,这里封装了Andrew算法求半凸包:先横坐标排序再Graham Scan。
线性扫描求交:
需要判断上下半凸包是否有交,有交一般来说就是没有直线能通过。有交但是能通过一条直线时需要特殊判断。
对于上下半凸包的点序列,讲其中一个视为点序列,另一个视为线段序列。判断点序列是否一直在线段序列的上方(或下方)。如果不是就说明有交。这个判断需要做两次,分别把上下半凸包视为点序列。
3. 伪代码
※ Map Overlay 的伪代码请参考 MapOverlay & Boolean Operations 实现讲解(PS/Photoshop布尔运算底层算法)
3.1 Half-plane Intersection
Algorithm INTERSECTHALFPLANES(H)
算法 INTERSECTHALFPLANES(H)
Input. A set H of n half-planes in the plane.
输入:由平面上n 张半平面组成的一个集合H
Output. The convex polygonal region C := ∩ h∈H h.
输出:凸多边形区域 C := ∩ h∈Hh
1. if card(H) = 1
1. if (card(H) == 1)
2. then C <

本文详细探讨了如何利用线性规划和Half-planeIntersection算法解决CG2017PA5-2FruitNinja项目中的问题,包括数学原理、半平面无限化处理、不同解法对比及可视化示例。重点介绍了两种方法的优缺点和时间复杂度分析。
:CG2017 PA5-2 FruitNinja(水果忍者)· 下&spm=1001.2101.3001.5002&articleId=126436135&d=1&t=3&u=14f50768e6c948cfb80b11b3a000e0f3)
1243

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



