我有 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具有相同的权重。
答案 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并停止将预算分配到达到其上限的存储桶。