我想将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
有一个好的算法吗?
答案 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
:
h(k) = k mod m
将n个球分配到m个桶如果diff
,n 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是您可以根据需要调整的参数。值越大,随机性越高,值越小,性能越好。您可以尝试许多测试用例,并提供适合您的最佳价值。