Задание №27 — Оптимальный алгоритм для большого количества данных
Для участников велогонки на каждом километре кольцевой трассыс двусторонним движением установлены пункты питания. Длина кольцевой трассы равна N километров. Нулевой и N-й километры трассы находятся в одной точке. Известно количество комплектов питания в каждом из пунктов на трассе. В каждый пункт комплектыпитания доставляет отдельный электрокар. Стоимость доставки питания вычисляется как произведение количества комплектов питания на расстояние от мобильного цеха их подготовки до пункта питания спортсменов на трассе. Мобильный цех подготовки комплектов расположен в одном из пунктов питания на трассе таким образом, что общая стоимость доставки из цеха во все пункты минимальна. Определите минимальную суммарную стоимость доставки питания для спортсменов из цеха его подготовки в пункты питания на трассе.
Входные данные:
Дано два входных файла (файл A и файл B), каждый из которых в первой строке содержит число N (1 ≤ N ≤ 10 000 000) – количество пунктов питания на кольцевой трассе. В каждой из следующих N строк находится число – количество комплектов питания на пункте (все числа натуральные, количество комплектов питания на каждом пункте не превышает 1000). Числа указаны в порядке расположения пунктов питания спортсменов на трассе, начиная с первого километра. В ответе укажите два числа: сначала значение искомой величины для файла А, затем – для файла B.
Типовой пример организации данных во входном файле:
6
8
20
5
13
7
19
При таких исходных данных, если пункты питания установлены на каждом километре трассы, необходимо открыть мобильный цех подготовки комплектов питания для спортсменов в пункте 6. В этом случае сумма транспортных затрат составит:
1 ∙ 7 + 0 ∙ 19 + 1 ∙ 8 + 2 ∙ 20 + 3 ∙ 5 + 2 ∙ 13.
Типовой пример имеет иллюстративный характер. Для выполнения задания используйте данные из прилагаемых файлов.
Предупреждение: для обработки файла B не следует использовать переборный алгоритм, вычисляющий сумму для всех возможных вариантов, поскольку написанная по такому алгоритму программа будет выполняться слишком долг.
Правильный ответ
141530 18192010182272
Пояснение
Решение:
Занумеруем пункты числами (пункт — это -й километр), вес пункта — количество комплектов питания. Трасса кольцевая и движение двустороннее, поэтому расстояние от цеха в пункте до пункта равно , где . Нужно найти , где .
Прямой перебор всех с пересчётом суммы — это , для файла B это нереально. Заметим, что при фиксированном пункты разбиваются на две дуги: до шагов вперёд (там расстояние равно смещению ) и до шагов назад (расстояние равно смещению ). Так как , каждый пункт учитывается ровно один раз, и (индексы по модулю ).
Обе суммы берутся по окну постоянной длины, которое сдвигается вместе с . Продублируем массив весов () и построим две префиксные суммы: и . Тогда, подставляя и , получаем Каждое значение считается за , весь алгоритм — за .
def solve(name):
f = open(name)
n = int(f.readline())
w = [int(f.readline()) for _ in range(n)] # w[c] — пункт (c+1)-го километра
a = n // 2 # смещения «вперёд»: 0, 1, ..., a
b = (n - 1) // 2 # смещения «назад»: 1, 2, ..., b (a + b + 1 = n)
ww = w + w # удваиваем массив, чтобы не считать индексы по модулю
p1 = [0] * (2 * n + 1) # p1[t] = сумма ww[0..t-1]
p2 = [0] * (2 * n + 1) # p2[t] = сумма i*ww[i] для i = 0..t-1
for t in range(2 * n):
p1[t + 1] = p1[t] + ww[t]
p2[t + 1] = p2[t] + t * ww[t]
best = None
for c in range(n):
hi = c + a + 1
fwd = (p2[hi] - p2[c]) - c * (p1[hi] - p1[c])
lo = c + n - b
bwd = (c + n) * (p1[c + n] - p1[lo]) - (p2[c + n] - p2[lo])
cost = fwd + bwd
if best is None or cost < best:
best = cost
return best
print(solve('A.txt'), solve('B.txt'))Проверка на примере из условия (, веса ): минимум достигается в пункте 6 и равен .Для файла A минимум равен (цех в пункте ), для файла B — .Ответ: 141530 18192010182272