算法:约束max-min< = diff的随机分布

时间:2012-10-18 14:19:49

标签: algorithm

我想将n balls随机地放入m buckets ,约束

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

Input: 
  ballCount: n
  bucketCount: m 
  allowedDiff: diff

Output: 
  ballCount distribution for buckets

有一个好的算法吗?

4 个答案:

答案 0 :(得分:3)

要分配球,只需沿着线向下,要求一个随机数[0,1),如果它小于1 /(剩余的总桶数)将一个球放入垃圾箱并继续前进到下一个垃圾箱。如果在此结束时,你仍然有剩余的球,评估箱之间的差异,如果箱子与允许的忽略箱一样远,这个通道的最大值。通过找到最小值并忽略任何超过minimum+difference-1的球来执行此操作,重复此过程直到您分配了所有球。

该算法的复杂性取决于球的数量(n)和桶的数量(m)。它的复杂性为O(mn)

我们可以通过意识到每个铲斗必须包含一定数量的球,例如5个铲斗和10个球,每个铲斗必须至少有1个球,每个铲斗必须包含一定数量的球。因此,在执行主算法之前,我们可以通过将球“预先放置”到每个桶中来节省一半的运行时间。

要计算可预先放置的球的数量,我们只需将球的数量除以球的数量n/m,然后取下这个球的最低点,以便a = ceiling(n/m)b = floor(n/m) < / p>

现在b应该是每个桶iff a-b = diff可能的最小球数。如果方程式最初不正确,有很多种方法可以解决这个问题,例如

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

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

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

答案 1 :(得分:1)

最简单的方法是生成和测试循环:

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

可能还有其他方法效率更高,但这是最容易编码的方法。

答案 2 :(得分:0)

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

如果diffn mod m == 0将为0,否则为1。

答案 3 :(得分: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是您可以根据需要调整的参数。值越大,随机性越高,值越小,性能越好。您可以尝试许多测试用例,并提供适合您的最佳价值。