【问题标题】:Generating 100 balls at random position within restricted space (has radius and no overlapping)在受限空间内的随机位置生成 100 个球(有半径且没有重叠)
【发布时间】:2013-07-16 02:47:47
【问题描述】:

例如,受限空间为100 x 100 x 100大,每个球的半径为5,我需要在这个空间内随机位置生成100个这样的球,不允许重叠。我想出了两种方法:

  1. 使用 srand 得到 100 个位置,然后检查删除相互重叠的球(检查两个球的中心距离是否小于半径的两倍),然后生成另一个 x 个球( x 是删除的球数)并不断重复该过程,直到 100 个球不重叠。

  2. 首先将空间划分为 100 个立方体,并使用srand 将每个球放置在其分配的立方体内,这样它们就不会重叠。

我觉得第一种方式在随机方面更合适,但太费时,第二种方式又快又容易,但我不确定随机的想法。而这个模型正试图模拟分子在空气中的位置。也许这两种方法都不好,如果有更好的方法,请告诉我。提前致谢!

编辑: @Will 为我提供了一个与我原来的第一种方法相似但更简洁的选项;每次添加新球时,检查它是否与任何现有球重叠,如果重叠,则重新生成。复杂度是1+2+3...+(n-1),大约是O(n^n)。我仍然想知道是否有更快的算法。

编辑2: 抱歉 1+2+..n 应该是 n^2

【问题讨论】:

  • 第二个。什么,你需要这个答案吗?我宁愿在算法上花更少的时间,也不愿真正随机。第三种选择,丢球。然后将球放在尚未覆盖的区域。如果你能弄清楚这个算法,你可能应该有一个大师。正如我已经提到的,我有一个 derpsters。
  • 感谢@Will 的回复,虽然我在理解derp 这个词时遇到了一些困难(我自己不是本地演讲者)。我现在在读本科,只是帮助我朋友的化学研究。当你说大师时,你是在暗示这是一个很深的问题吗?我认为您的第三个选项实际上很棒。每次我生成一个新球时,我都会检查它是否与现有球重叠,如果有,则重新生成。非常感谢!
  • 对于您的编辑,您建议 1+2+3... + n-1 的复杂度是 O(n^n) 但实际上是 O(n^2)。跨度>
  • @user1125600 谢谢,已更正!
  • @Arch1tect:“derp”是愚蠢的声音,我猜......无论如何,第三个建议的简单实现可能会导致一大群球而不是均匀分布。

标签: algorithm random complexity-theory big-o


【解决方案1】:

您可以执行 O((n + f) log n) 算法,其中 f 是失败尝试的次数。本质上,花费时间过长的问题是找到与哪些相邻的球重叠。您可以使用称为 KD 树的外部数据结构来有效地存储球的位置。然后你可以通过KD树查找你“最近”的相邻球。这将花费 O(log n) 时间。确定它们是否重叠,然后将球添加到空间和 KD 树中——插入是 O(log n) 操作。总共有 n 个球,每个球取 O(log n) 将是 O(n log n),失败的尝试将是 O((n+F)*log n)。 CGAL(计算几何算法库)提供了一个很好的 KD-tree 实现。这是 CGAL 的链接和 KD 树的链接:

http://www.cgal.org/

https://en.wikipedia.org/wiki/K-d_tree

还有其他结构,例如 K-D 树,但对于您的情况,这将是最容易使用的。

如果您想避免使用花哨的数据结构,可以在空间上计算网格。将整个空间中的每个随机球插入其网格单元中。然后在检查重叠时,您只需要检查相邻单元格中的球(假设球大小不会重叠超过一个邻接)。这不会提高整体时间复杂度,但在计算机图形学中是一种常用方法,可提高邻居查找例程的执行时间。

【讨论】:

  • 一般来说,我不认为这将是O(n*log(n)) 方法 - 它将是O((n + F)*log(n)) 其中F 是插入失败的次数(由于球重叠)。如果球的位置是随机选择的,F 会变得非常大F >> O(n)
  • 这是真的,但是在如此大的空间中(球的体积约为 222,而空间的总体积为 1000000),超过 100 个随机球失败的尝试很可能很小。我会相应地编辑我的帖子,谢谢!
  • 对不起,我的意思是一个球的体积是523。
【解决方案2】:

您可以将区域划分为 8,000 个 5 x 5 的立方体,而不是将区域划分为 100 个立方体,然后将球放在 100 个这些立方体的中心。这样球仍然随机放置在空间中,但不能重叠。 编辑:另外,在检查球是否重叠时,您可能需要考虑使用一种数据结构,该结构允许您仅检查最接近您正在检查的球的球。检查所有这些是浪费的,因为空间完全不同侧的球不可能重叠。我对八叉树不太熟悉,但如果你真的想优化你的代码,你可能想看看它们。

【讨论】:

  • 半径是 5 所以它应该是 10 x 10 的 1000 的立方体,我认为这是迄今为止最好的解决方案。非常感谢!
【解决方案3】:

球体的体积大约是空间体积的 1/1900,因此如果您只是选择随机位置并检查重叠,则不必重新生成很多。如果你真的只需要 100 个,那么使用像八叉树这样的奇特算法来检查碰撞将是一种浪费。

当然,一旦你编写代码,有人会要求你为 10,000 个球体而不是 100 个球体进行编码,所以我刚才所说的一切都是错误的。

我喜欢 Chris 的建议,即把它们放在随机选择的立方体中。也许不是最现实的,但接近且简单得多。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-28
    • 1970-01-01
    相关资源
    最近更新 更多