Пусть z - действительный параметр. Мое понимание проблемы заключается в том, что вы хотите найти z таким образом, что когда ведро i распределяется max (MIN i, min (MAX i, W i z)), сумма распределений равна x.
Вот алгоритм O (n log n) -time (есть, вероятно, линейно-временный, но если он существует, он, вероятно, будет более сложным). Интуитивно, что он делает, это увеличить z непрерывно, пока сумма распределений не будет равна x.
Производная суммы по z представляет собой сумму производных для каждого ведра.Производное ведра я равен 0 при г < а, то W я для < г < Ь, то 0 при б < г, где а = MIN я/Вт я является первой критической точкой, и 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]
Что вы подразумеваете под «минимальным и максимальным приоритетами над весами»? Можем ли мы иметь оставшиеся деньги? Если бы ведро A имело максимум 25 долларов, вы бы хотели, чтобы ковши A и B имели только 25 долларов, поскольку их весы равны или мы продолжаем добавлять деньги в B? – eigenchris
Остатки не допускаются. Макс. И мин применяются только к отдельному ковшу. Так что если A maxed на 25 долларов, B все равно может подняться выше, потому что он не попал в макс. Вес должен применяться, если колпачки не попадают на заданный уровень объявления. – eymlo
@collapsar Вы могли бы также превратить это в ответ. – eigenchris