Algorithm 三角形划分

Algorithm 三角形划分,algorithm,language-agnostic,computational-geometry,Algorithm,Language Agnostic,Computational Geometry,这是2010年太平洋ACM-ICPC竞赛中的一个问题。其要点是试图找到一种方法,将三角形内的一组点划分为三个子三角形,这样每个分区正好包含三分之一的点 输入: 边界三角形的坐标:(v1x,v1y),(v2x,v2y),(v3x,v3y) 一个数字3n

这是2010年太平洋ACM-ICPC竞赛中的一个问题。其要点是试图找到一种方法,将三角形内的一组点划分为三个子三角形,这样每个分区正好包含三分之一的点

输入:

  • 边界三角形的坐标:
    (v1x,v1y),(v2x,v2y),(v3x,v3y)
  • 一个数字
    3n<30000
    ,表示三角形内的点数
  • 3n
    点的坐标:
    (x_i,y_i)
    对于
    i=1…3n
输出:

  • 一个点
    (sx,sy)
    ,它将三角形分成3个子三角形,使每个子三角形正好包含
    n个点
拆分点将边界三角形拆分为子三角形的方式如下:从拆分点到三个顶点中的每个顶点绘制一条线。这将把三角形分成3个子三角形

我们保证这一点是存在的。任何这样的观点都足够了(答案不一定是唯一的)

以下是
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
    点时停止。从