包络算法优化 - 放圆的最佳位置

时间:2008-12-07 20:10:17

标签: algorithm optimization computer-science topology

我必须以最佳方式解决以下问题。

输入数据是:

  • 作为(x,y)整数坐标对给出的平面中的N个点
  • M指向同一平面,作为表示圆心的(x,y)整数坐标对。所有这些圈子的边缘都有(0,0)。

我需要找到一种方法来隔离具有属性的多个圆圈而不是任何“好”圆圈,从前N个点放置在所选圆圈中或所选圆圈的边缘没有任何点。

点数和圆圈的数量级为100,000。每个点检查每个圆的明显解决方案具有复杂度O(N * M)和100,000个圆和100,000个点,在具有64位SSE3单精度代码的Core 2 Duo上花费大约15秒。我竞争的参考实现只需要大约0.1秒的相同数据。我知道参考实现是O(Nlog N + Mlog M)。

我想过以下列方式优化算法。制作2个点数据副本,并根据x坐标和y坐标对副本进行排序。然后只使用位于[(xc - r,yc - r)定义的方格中的点; (xc + r,yc + r)],其中(xc,yc)是“当前”圆的中心,半径为r。我可以使用二进制搜索在该间隔中找到点,因为现在我使用已排序的数据。这种方法的复杂性应该是O(Nlog N + Mlog ^ 2 N),实际上它比参考更快但仍然明显慢。

我或多或少知道参考实现的工作原理,但有些步骤我不明白。我将尝试解释到目前为止我所知道的事情:

坐标为(Xc,Yc)的圆的半径为:

  • Rc = sqrt(Xc * Xc + Yc * Yc)(1)

那是因为(0,0)位于圆的边缘。

如果点P(x,y)在圆外,则以下的不等式必须为真:

  • sqrt((Xc-x)^ 2 +(Yc-y)^ 2)> Rc(2)

现在,如果我们将(1)中的Rc替换为(2),那么在我们进行一些简单的计算后,将方程式平方:

  • Yc<对于y,1 / 2y *(x ^ 2 + y ^ 2)-Xc * x / y(3.1)。 0
  • Yc&gt; 1 <2y *(x ^ 2 + y ^ 2)-Xc * x / y(3.2),y <1。 0
对于从输入数据中选择的任何(x,y)的给定圆C(Xc,Yc),

(3.1)和(3.2)必须为真。

为简单起见,我们先写几点:

  • A(x,y)= 1 / 2y *(x ^ 2 + y ^ 2)(4.1​​)
  • B(x,y)= - x / y(4.2)
  • E(Xc)= 1 / 2y *(x ^ 2 + y ^ 2) - Xc * x / y = A(x,y)+ Xc * B(x,y)(4.3)

我们可以看到,对于给定的圆C(Xc,Yc),我们可以将(3)写成:

  • Yc&lt;对于y> 1的所有点,MIN(E(Xc))(5.1) 0
  • Yc&gt;对于y <&lt;所有点,MAX(E(Xc))(5.2) 0

我们可以看到E(Xc)是关于Xc的线性函数,具有2个参数--A(x,y)和B(x,y)。这意味着基本上E(Xc)在欧几里德空间中表示具有2个参数的一族线。

现在这里是我不明白的部分。他们说,由于上段所述的属性,我们可以使用Envelope算法在O(1)摊销时间而不是O(N)时间内计算MIN()和MAX()。我不知道Envelope算法如何工作。

有关如何实施Envelope算法的任何提示?

提前致谢!


修改

问题不在于数学意义上的信封是什么 - 我已经知道了。问题是如何在更好的时间内确定包络O(n),显然它可以在摊销的O(1)中完成。

我有计算包络所需的函数族,并且我有一个所有可能参数的数组。如何以最佳方式解决最大化问题?

再次感谢!

6 个答案:

答案 0 :(得分:1)

答案 1 :(得分:1)

我没有数学背景,但我会分三个步骤解决这个问题:

  • 扔掉N中的大多数分数。这是棘手的部分。当从原点看时,每对点“遮蔽”一个“后面”的区域。该区域由两个光束分隔,这两个光束从点向外开始,指向原点,以及点之间的圆形交点。在极坐标中计算这个可能要简单得多。从随机对开始,然后一次看一个新点:如果它被遮挡,扔掉它;如果没有,找出它是否遮挡了你的集合中已经存在的任何点,然后重建包络的曲线集。重建包络曲线部分的测试应该花费几乎恒定的时间,因为阴影集不可能超过一定的小数。最坏的情况似乎是O(NlogN)。我无法想象任何解决方案都可以比O(N)更好,因为在任何情况下你都必须看每一点。

  • 扔掉M中的大多数点。这很容易:如果M点远离原点而不是距离包络集最远点的距离的一半,则它可以被抛出。这需要O(M)

  • 通过实际检查过滤M中的剩余点。它取决于N和M的分布,这需要多长时间,但我认为如果两个数字都很大且分布相似,那么几乎 O(1)。

总的来说,似乎可以在O(N log(N)+ M)中。但不保证;)

答案 2 :(得分:1)

  • 构建第一组中所有点的R-Tree
  • 对于第二组中的每个点,计算其圆的边界框并查找落在该边界框内的R树中的所有点(相对于返回的点数,O(n log n))
  • 检查每个返回点与当前正在考虑的点之间的距离;丢弃任何位于边界内但在圆圈外的人。

答案 3 :(得分:1)

我认为你可以用Voronoi图做到这一点:

  • 制作{N points} union {[0,0]}
  • 的Voronoi图
  • 不接触N个点的圆心恰好位于点[0,0]的Voronoi单元内,这是一个凸多边形
  • 过滤M个点,一个测试应该取O(log C)= O(log N)[其中C是单元格中顶点的数量[0,0]

总体复杂度应为O(N log N + M log N)

答案 4 :(得分:0)

考虑一下计算的其他方面。

例如,你显然比较了很多距离。每个人都接到一个SQRT的电话。为什么不比较“距离的平方”。 SQRT是一项代价高昂的计算。

答案 5 :(得分:0)

永远不要拿sqrt。将所有距离保留为正方形。这样做,你也可以比较它们,但时间减少了2-3倍。