【问题标题】:Efficient algorithm for finding spheres farthest apart in large collection查找大型集合中相距最远的球体的高效算法
【发布时间】:2010-02-16 21:28:12
【问题描述】:

我收集了 10000 - 100000 个球体,我需要找到相距最远的球体。

一种简单的方法是简单地将所有球体相互比较并存储最大距离,但这感觉就像算法的真正资源消耗。

Spheres 的存储方式如下:

Sphere (float x, float y, float z, float radius);

Sphere::distanceTo(Sphere &s) 方法返回球体两个中心点之间的距离。

例子:

Sphere *spheres;
float biggestDistance;

for (int i = 0; i < nOfSpheres; i++) {
    for (int j = 0; j < nOfSpheres; j++) {
        if (spheres[i].distanceTo(spheres[j]) > biggestDistance) {
            biggestDistance = spheres[i].distanceTo(spheres[j]) > biggestDistance;
        }
    }
}

我正在寻找的是一种算法,它以某种更智能的方式循环所有可能的组合,如果有的话。

该项目是用 C++ 编写的(它必须是),因此在 C/C++ 以外的其他语言中工作的任何解决方案都不太受关注。

【问题讨论】:

  • 澄清一下,你想要比 O(n^2) 更好的东西(这很糟糕)。嗯.....
  • distanceTo() 是否服从三角不等式? distanceTo() 是中心到中心还是表面到表面?球体在向量空间中有坐标吗?它是在欧几里得空间中,还是在弯曲度量的周围有黑洞?无论如何,你从哪里得到所有这些球体?球内有什么有趣的东西可以在 eBay 上出售,因为你似乎有很多?
  • @Craig 如果他们在真正的线上,那么排序将是 n log(n),但只有 O(n) 才能找到最小和最大坐标。假设半径或表面不是问题
  • BFS 搜索提供 O(b^d) 复杂度或 O(|E| + |V|)
  • @Mark:是的,这是作业。你是怎么猜到的? (除了 CS 老师喜欢大量失控的数据这一事实之外。)@Craig:是的,我知道可以进行一些改进 - 但我有一种感觉,我错过了一些东西。 =P @Paul:大声笑,我认为球体的内部充满了空隙。如果你想买一些,我相信我们可以安排一些东西。 ;-)

标签: algorithm collections geometry comparison


【解决方案1】:

S 点集合中任意两点之间的最大距离称为 diameter。求一组点的直径是计算几何中的一个众所周知的问题。一般来说,这里有两个步骤:

  1. 找到由每个球体中心组成的三维凸包 - 比如说,使用 CGAL 中的 quickhull 实现。

  2. 找到船体上相距最远的点。 (船体内部的两个点不能是直径的一部分,否则它们会在船体上,这是矛盾的。)

使用 quickhull,您可以在平均情况下的 O(n log n) 和最坏情况下的 O(n2) 运行时间中完成第一步。 (在实践中,quickhull 明显优于所有其他已知算法。)如果您可以保证球体排序的某些属性,则可以保证更好的最坏情况界限,但这是一个不同的主题。

第二步可以用 Ω(h log h) 来完成,其中h 是船体上的点数。在最坏的情况下,h = n(每个点都在船体上),但如果你有数千个随机球体,这不太可能。一般来说,h 会比n 小很多。这是an overview of this method.

【讨论】:

  • +1:我在看到这个帖子后删除了我的帖子,因为这个帖子是一个超集和更好的答案。
  • 我会更详细地描述这些步骤,但这是家庭作业。但是,CGAL 提供了源代码,因此查看它是了解这里发生的事情的一个很好的开始。
  • 经过一些简短的谷歌搜索后,我想我也会添加这个链接:personal.kent.edu/~rmuhamma/Compgeometry/MyCG/ConvexHull/…
  • @JohnFeminella - 该概览链接似乎已失效。我正在处理一个类似的问题,导致我来到这里,我点击了那个链接。 :-(
【解决方案2】:

您能否将这些球体存储在BSP Tree 中?如果这是可以接受的,那么您可以从查找包含距离最远的球体的树的节点开始。然后您可以继续沿着树向下,直到到达各个球体。

【讨论】:

  • 我也想过树形结构,但是我还没有研究过BSP树,谢谢你的回复。 =)
【解决方案3】:

您的问题看起来可以使用图表来解决。由于球体 A 到球体 B 的距离与球体 B 到球体 A 的距离相同,因此您可以尽量减少必须进行的比较次数。

我认为您在此处看到的内容称为Adjacency List。您可以建立一个,然后遍历它以找到最长的距离。

您可以使用的另一种方法仍然会给您一个 O(n^2),但您可以最大限度地减少您必须进行的比较次数。您可以将计算结果存储到哈希表中,其中键是边的名称(因此 AB 将保存从 A 到 B 的长度)。在执行距离计算之前,请检查哈希表中是否存在 AB 或 BA。

编辑

使用邻接列表方法(基本上是 Breadth-First Search),您会得到 O(b^d) 或最坏情况 O(|E| + |V|) 的复杂度。

【讨论】:

  • 真的,我不知道 BFS 是一种如此低效的算法。我的眼睛已经睁开了。
  • 构建邻接列表所花费的时间与蛮力解决方案一样多。
【解决方案4】:

保罗让我的大脑开始思考,你可以通过改变来优化一下

for (int j=0; j < nOfSpheres; j++) 

for (int j=i+1;  j < nOfSpheres; j++) 

您无需将球体 A 与 B AND B 与 A 进行比较。这将使搜索 O(n log n)。

--- 加法-------

使该计算变得昂贵的另一件事是 DistanceTo 计算。

distance = sqrt((x2 - x1)^2 + (y2 - y1)^2 + (z2 - z1)^2)

这是很多数学问题。您可以通过检查是否

来减少它
((x2 - x1)^2 + (y2 - y1)^2 + (z2 - z1)^2 > maxdist^2

删除 sqrt 直到结束。

【讨论】:

  • 不,这仍然是 O(n^2),但它将支票数量减少了一半(也即将发布)。
  • 是的,我知道。 sqrt 很贵。
  • 我想知道如果你在某个昏暗 N>1 的空间中有坐标,那么获取主成分是否有帮助。
  • 您不需要检查 maxdist^2 因为平方距离已经存储在 maxdist 中了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-11
  • 2014-07-11
  • 1970-01-01
  • 2010-12-06
  • 1970-01-01
  • 2020-08-21
相关资源
最近更新 更多