加权平均分布算法

时间:2015-02-25 16:51:43

标签: algorithm optimization distribution

我有 N 个桶,每个桶的标准化权重为 W i 。我想按重量向每个桶分配$ x 。每个存储桶都有一个最小$( MIN i )和最大$( MAX i )算法需要履行。每个桶的最小值和最大值优先于权重。这个问题在多项式时间内是否可解,算法如何?

示例:

4个桶,A,B,C,D

A:W A = 100,MIN A = 0,MAX A = 150

B:W B = 100,MIN B = 0,MAX B = 60

C:W C = 1,MIN C = 20,MAX C = 150

D:W D = 1,MIN D = 30,MAX D = 150

总计$ = $ 150

预期结果:

答:50美元

B:50美元

C:20美元

D:30美元

请注意,C和D正在使用他们的分钟,其余的美元被均分,因为A和B具有相同的权重。

2 个答案:

答案 0 :(得分:1)

设z是一个真实的参数。我对这个问题的理解是你想找到这样的结果,当桶i被分配为max(MIN i ,min(MAX i ,W i < / sub> z)),分配总和等于x。

这是一个O(n log n)时间算法(可能是一个线性时间算法,但如果确实存在,它可能会更复杂)。直观地说,它的作用是连续增加z,直到分配总和等于x。

z中和的导数是每个桶的导数之和。对于z <1,桶i的导数为0。 a,然后W i 表示&lt; z&lt; b,然后0表示b < z,其中a = MIN i / W i 是第一临界点,b = MAX i / W i 是第二个关键点。我们对这些关键点进行排序,然后找出所得到的分段线性函数。在Python 3中(故意避免使用一些Python习语):

import collections

Bucket = collections.namedtuple('Bucket', ('weight', 'min', 'max'))
Event = collections.namedtuple('Event', ('key', 'i', 'derivative'))


def allocate(total, buckets):
  n = len(buckets)
  events = []
  derivative = 0
  residual = total
  derivatives = []
  for i in range(n):
    bucket = buckets[i]
    events.extend([Event(bucket.min / bucket.weight, i, bucket.weight),
                   Event(bucket.max / bucket.weight, i, 0)])
    residual -= bucket.min
    derivatives.append(0)
  events.sort()
  z = 0
  for event in events:
    if derivative > 0:
      w = z + residual / derivative
      if w <= event.key:
        z = w
        break
    residual -= derivative * (event.key - z)
    derivative -= derivatives[event.i]
    derivatives[event.i] = event.derivative
    derivative += derivatives[event.i]
    z = event.key
  allocations = []
  for i in range(n):
    bucket = buckets[i]
    allocations.append(max(bucket.min,
                           min(bucket.max,
                               bucket.weight * z)))
  return allocations

print(allocate(150,
               [Bucket(100, 0, 150),
                Bucket(100, 0, 60),
                Bucket(1, 20, 150),
                Bucket(1, 30, 150)]))
# [50.0, 50.0, 20, 30]
print(allocate(100,
               [Bucket(40, 42, 55),
                Bucket(40, 0, 100),
                Bucket(20, 0, 4)]))
# [48.0, 48.0, 4]

答案 1 :(得分:0)

第1步:分配所有最低预算

in your example: 
( 0, 0, 20 ,30)

步骤2:如果没有边界,则计算理想的分配:

in your example: 
(100/202)*150 =74
(100/202)*150 =74
(1/202)*150 = 0.74
(1/202)*150 = 0.74

步骤3:从理想中减去“当前分配”:

in your example:
0 - 74 = -74
0 - 74 = -74
20 - 0.74 = 19.26
30 - 0.74 = 29.26

步骤4:将美元/分配给第3步中的最低值

in your example:
-74 is the lowest value
so just assign a dollar to the first one with the lowest value

步骤5:重复步骤3和4并停止将预算分配到达到其上限的存储桶。