【问题标题】:Filling a plane with random points用随机点填充平面
【发布时间】:2016-10-02 08:20:12
【问题描述】:

我想用随机放置的点填充一个平面,检查它们是否重叠(如果重叠,将其中一个移动到空白处),然后计算它们之间的平均距离。稍后我计划将其扩展到 3D,以便它在盒子中包含粒子。 我知道必须有更好的方法来做到这一点,但这就是我想出的。在平面上放置随机点:

int pos[NUMBER][2];    /* Creates an array of NUMBER amount of points with x and y coordinate */
int a, b;
srand( time(NULL) );
for(a=0;a<NUMBER;a++)
      for(b=0;b<2;b++)
         pos[a][b]=rand()%11; /* Using modulus is random enough for now */

下一阶段是寻找重叠的点:

    for(a=0;a<NUMBER-1;a++)
      for(b=a+1;b<NUMBER;b++)
        if( pos[a][0] == pos[b][0] && pos[a][1] == pos[b][1])
           printf("These points overlap:\t", pos[a][0], pos[a][1]);

现在,当我确定哪些点重叠时,我必须移动其中一个,但是当我这样做时,新位置的点可能与之前的点之一重叠。有没有公​​认的方法来解决这个问题?一种方法是具有中断条件的无限 while(true) 循环,但这似乎非常低效,尤其是当系统变得密集时。 谢谢!

【问题讨论】:

  • 我不知道“接受”的方式,但我想我可以在 O(NUMER*log(GRID_SIZE)) 时间内提供解决方案,其中GRID_SIZE 是可能职位的总数。小参数可能更慢,但大参数更快。
  • 为什么不在放置点时检查重叠?您需要某种数据结构才能使其相当有效。

标签: c random


【解决方案1】:

这是我认为可行的解决方案的草图:

  1. 你的点生成算法不错,可以保持原样。

  2. 检查重叠的正确时间已经是生成点的时间。我们只是生成新的点,直到我们生成一个不与之前的任何重叠的点。

  3. 要快速找到重叠,请使用哈希表,例如来自 '''glib''' 的哈希表。关键可以是两个 int32_t 打包成一个 int64_t 联合:

    typedef union _Point { struct { int32_t x; int32_t y; }; int64_t hashkey; } Point;

  4. 使用哈希表的“遍历所有键”功能构建输出数组。

我无法对此进行测试,但它应该可以工作。这假设平面相对于点的数量很大,因此重叠的可能性较小。如果相反,你可以颠倒逻辑:从一个完整的平面开始,随机添加孔。

该算法的平均复杂度为 O(n)。

【讨论】:

  • a) 因为我们知道网格上的点数和位置数,所以检查完整性是微不足道的。无论如何,纾困是愚蠢的。
  • b) 即使是超过一半的董事会也不应该出现。此时,选择包含点的地方会更快。 (其工作原理完全相同。)
  • c) 由于第二个点被重复放置在第一个点上而导致的救助应该不被接受,因此您的算法不能保证终止。 (这当然不太可能。)让最坏的情况变得更糟。平均不过看起来不错。
  • @Hermann,你是对的,我已经相应地编辑了我的答案。
  • 将您的 (b) 纳入解决方案,不终止的可能性很小。对于一个合适的随机函数选择,它最终应该生成所有可能的输出。
【解决方案2】:

正如您暗示的那样,它也应该适用于高密度,最好的做法是创建一个 2D 布尔数组(或位向量,如果您想节省空间),其中所有元素最初都设置为 false。然后循环 NUMBER 次,生成一个随机坐标,并检查数组中的值是否为真。如果为真,则生成另一个随机坐标。如果为 false,则将坐标添加到列表中,并将数组中的相应元素设置为 true。

以上假设您想要确切 NUMBER 分,并且有一个完全一致的机会放置它们。如果这些约束中的任何一个都不是必需的,那么还有其他可能使用更少内存的算法。

【讨论】:

  • 这假设坐标的最大尺寸有一个相当低的界限,并且不适用于真实坐标(不是问题中的要求,而是问题的合理扩展)。
  • 这个想法是将其扩展到真实坐标,是的。无论如何,这对我来说太复杂了,不过我很感激所有的答案。
【解决方案3】:

一种解决方案是随机放置点,看看它们是否重叠,然后重试重叠。为避免测试每个点,您需要按空间设置索引 - 如果您有一个 100*100 的平面和 3-4 的截断,您可以使用 10*10 的方格。然后你必须搜索四个方格来检查你没有命中。

但是还有其他方法可以做到这一点。将点均匀地放置在网格上将创建泊松分布。因此,对于每个点,您都可以使用泊松分布创建一个随机数。当您获得 2 个或更多时会发生什么?这种方法迫使你回答这个问题。也许您人为地夹到一个,也许您移动到相邻的插槽中。此方法不会精确创建 N 个点,因此如果您必须有 N 个点,您可以放入一个软糖(随机添加/删除最后几个点)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-22
    • 2017-06-04
    • 1970-01-01
    • 2011-01-23
    相关资源
    最近更新 更多