2012-10-18 63 views
1

我想把n ballsm buckets随机,以约束算法:有约束的最大最小随机分布<= DIFF

ballCountMax-ballCountMin <= diff 
ballCountMax-ballCountMin as random as possible 

Input: 
    ballCount: n 
    bucketCount: m 
    allowedDiff: diff 

Output: 
    ballCount distribution for buckets 

是否有一个好的算法?

+0

该限制有多严格?也就是说,如果你建立了一个基于这个约束的概率分布,它仍然有可能产生一个可能稍微超出它的集合 –

+0

球是否可区分?还是他们都一样? – jozefg

+0

@jozefg,他们都是一样的,只是球计数重要 – smilingpoplar

回答

3

要分配球,只需沿着线路,要求随机数[0,1),如果它小于1 /(剩余的水桶总数)将一个球放入容器并移动到下一个容器。如果在最后,你仍然有球,评估箱之间的差异,如果箱距离允许忽略这个通道最大的箱子。通过查找最小和忽略任何球比minimum+difference-1重复以上这个过程,直到你已经发布的所有你的球做到这一点。

的该算法的复杂性依赖于球(n)的数量和桶的数量(M)。它的复杂度为O(mn)

我们可以通过认识到每个桶必须包含球的某个最小数目,例如用5桶和10个球为2的差,计算每个桶必须具有至少1球显著加快这。因此,在执行主算法之前,我们可以通过将球预置到每个桶中来节省一半的运行时间。

要计算,我们只是必须通过桶n/m的数除以球的数量预先放置的球的数量,并采取地面和这个上限,以便a = ceiling(n/m)b = floor(n/m)

现在b应该是最小数每个桶可能的球iff a-b = diff。有许多方法来解决这个问题,如果等式不最初如此,比如

while(a-b<diff){ 
    ++a; 
    --b; 
} 

注意,在所有情况下,此方法将返回不正确的结果,因此增加一个检查a-b = diff是必要的。

因此,我们可以预先放置b球。

+0

好主意,模拟放置球 – smilingpoplar

+0

呀的过程中,挂在我想到了一个优化 – jozefg

+0

公顷,你的优化是一个有点像我只是想 – smilingpoplar

1

最简单的方法将是一个产生和测试循环:

do { 
    distribute_balls_at_random(); 
} while (constraint_not_satisfied()) 

有可能是更有效的其他方法,但是这将是最简单的代码。

+0

它可以工作,但我想知道是否有更好的算法。 – smilingpoplar

+0

@smilingpoplar - 如果随机分布滚珠过程是球已经在每个桶的数量敏感(即,低当铲斗有更多的球),这可能是足够有效。 –

0

以下是O(n)算法与diff <= 1

diff将为0,如果是n mod m == 0,则为1,否则为1。

+1

不,我想尽可能随机差异,不只是0或1 – smilingpoplar

0
function do(int n, int m, int diff){ 
     buckets = array of size m with initial values = 0 
     while(n-- > 0){ 
      int limit = 1000; 
      while(limit > 0){ 
       int idx = random number from 0 to m 
       buckets[idx]+=1 
       int min = min_element(buckets) 
       int max = max_element(buckets) 
       if(buckets[max] - buckets[min] <= diff) break 
       buckets[idx]-=1 
       limit-- 
      } 
      if(limit == 0){ 
       int min = min_element(buckets) 
       buckets[min]++; 
       int max = max_element(buckets) 
       if(buckets[max] - buckets[min) > diff) 
        return false; //there is no valid distribution 
      } 

     } 
     print buckets 
     return true 
} 

limit是一个您可以随意调整的参数。更高的值确保更多的随机性,更少的值确保更好的性能。您可以尝试很多测试用例,并以适合您的最佳值出来。

+0

我认为有很多优化的空间。例如,不是调用min_elemnt和max_element,而是可以将它们合并到一个函数中,并将两者的计算值存储在通过引用传递的2个变量中。但无论如何,这是最简单的版本 –