在similar question中,我问过如何使用权重分布整数。我很好奇如果给每个分配“桶”的最小值,人们将如何解决这个问题。通过施加最小值,这似乎是一个更加困难的问题。这是我的贪婪尝试,不起作用:
def distribute(available, weights_and_mins):
distributed_amounts = []
total_weight = sum([i[0] for i in weights_and_mins])
for weight, minimum in weights_and_mins:
weight = float(weight)
p = weight / total_weight
distributed_amount = round(p * available)
if distributed_amount < minimum:
distributed_amount = minimum
distributed_amounts.append(distributed_amount)
available -= distributed_amount
total_weight -= weight
return [int(i) for i in distributed_amounts]
print distribute(10, ((10,1), (2,5), (2,4)))
print distribute(1000, ((10,1), (2,5), (2,4)))
目前,这些值分配为[7,5,4],这是16,比我们分发的数据多6。输出应为[1,5,4],因为这满足所有列的最低要求。随着我们分配的价值增长,分布应越来越接近正确的加权分布。例如,通过分配1000,算法正确地将值分配为[714,143,143]。
作为旁注,我的目的是在多个列之间分配可用空间(宽度)。所有列都具有“获取”所需的最小大小并且至少显示其一些数据,并且随着可用空间的增长,一些列更需要空间。我将此视为此算法的一种实际用途,但我不希望这是对GUI设计的讨论。
这个问题有哪些解决方案?越简越好。
答案 0 :(得分:1)
您应首先分配最低金额并相应更新。之后您可以相应地分配剩余金额。
prior_available = available
allocated = [i[1] for i in weights_and_mins]
available = available - sum(allocated)
if available < 0:
The hell breaks loose
total_weight = float(sum([i[0] for i in weights_and_mins]))
for i in len(weights_and_min):
v = round( weights_and_min[i][0]*prior_available/total_weight )
nv = min( available, max(v-allocated[i],0) )
allocated[i] += nv
available -= nv