Algorithm 三角形划分
这是2010年太平洋ACM-ICPC竞赛中的一个问题。其要点是试图找到一种方法,将三角形内的一组点划分为三个子三角形,这样每个分区正好包含三分之一的点 输入:Algorithm 三角形划分,algorithm,language-agnostic,computational-geometry,Algorithm,Language Agnostic,Computational Geometry,这是2010年太平洋ACM-ICPC竞赛中的一个问题。其要点是试图找到一种方法,将三角形内的一组点划分为三个子三角形,这样每个分区正好包含三分之一的点 输入: 边界三角形的坐标:(v1x,v1y),(v2x,v2y),(v3x,v3y) 一个数字3n
- 边界三角形的坐标:
(v1x,v1y),(v2x,v2y),(v3x,v3y)
- 一个数字
,表示三角形内的点数3n<30000
点的坐标:3n
对于(x_i,y_i)
i=1…3n
- 一个点
,它将三角形分成3个子三角形,使每个子三角形正好包含(sx,sy)
n个点
n=2
(6点)的问题示例。我们得到了大三角形中每个有色点的坐标和每个顶点的坐标。分割点用灰色圈出
有人能推荐一个比O(n^2)
更快的算法吗?这里有一个O(n logn)
算法。我们假设没有简并
高层思想是,给定一个三角形PQR
P
C \
/ S\
R-----Q
我们首先将中心点C
置于p
。向R
方向滑动C
,直到三角形CPQ
内有n
点,段CQ
上有一个(S
)。向Q
方向滑动C
,直到三角形CRP
不再有缺陷(扰动C
完成)或CP
达到一个点。在后一种情况下,滑动C
远离P
,直到三角形CRP
不再有缺陷(我们完成了)或CQ
到达一个点,在这种情况下,我们再次开始向Q
滑动C
显然,该实现无法“滑动”点,因此对于涉及C
的每个三角形,对于该三角形的每个顶点S
,而不是C
,将三角形内的点存储在二元搜索树中,按S
的角度排序。这些结构足以实现此动力学算法
我断言这个算法是正确的,没有证据
至于运行时间,每个事件都是一个点-线交叉点,可以在时间
O(logn)
中处理。角度PC
和QC
和RC
都是单调的,因此O(1)
每一条线最多只击中一次每个点。这里有一种方法,每一条线都需要成本n的O(logn)传递
每个过程从一个初始点开始,该初始点将三角形分为三个子三角形。如果每个都有n个点,我们就完成了。如果不是,考虑距离最远的距离最远的子三角形。假设它有太多,就目前而言。不平衡总和为零,因此其他两个子三角形中至少有一个点太少。第三个子三角形要么太少,要么正好有n个点——否则原始子三角形的差异不会最大
取最不平衡的子三角形,并考虑沿中心线移动中心点。这样做时,最不平衡点的不平衡将减少。对于三角形中的每个点,移动中心点时,可以计算出该点何时穿过或穿过最不平衡的次三角形。因此,您可以在时间n中计算出移动中心点的位置,以给出最不平衡的三角形的任何所需计数
当你移动中心点时,你可以选择点是否从最不平衡的子三角中移入,但你不能选择其他两个子三角中的哪一个-但你可以很容易地预测它们从直线的哪一侧滑动中心点,所以你可以沿着这条线移动中心点,以获得移动后的最小最大偏差。在最坏的情况下,所有移动的点都进入或离开完全平衡的子三角。但是,如果不平衡的子三角有n+k个点,通过移动其中的k/2,最坏的情况下,可以移动到它和先前平衡的子三角以k/2的速度向外移动的情况。在另一个方向上,第三个副三角可能仍然不平衡高达k,但在这种情况下,第二次通过将最大不平衡降低到k/2以下因此,在大不平衡的情况下,我们可以在上述算法的两个过程中,最坏情况下减少常数因子,因此在O(logn)过程中,不平衡将足够小,以至于我们处于特殊情况下,我们担心最多超过一个点。在这里,我将猜测,在一个程序中,这种特殊情况的数量实际上是可枚举的,并且成本相当于一个小的常量加法。主要思想是:如果我们已经得到了线,我们可以尝试使用线性搜索在其上找到一个点。如果行不够好,我们可以使用二进制搜索来移动它
A
的方向对点进行排序。按B
和C
对它们进行排序A
的当前范围设置为所有点A
的范围中选择2个中点。这两个点定义了“A”的子范围。在这些点之间找到一些线AD
B
和AD
之间的所有点(从BA
开始)。找到n
点时停止。从