Тема 27. Программирование

27.01 Передвижение по магистрали

Вспоминай формулы по каждой теме
Решай новые задачи каждый день
Вдумчиво разбирай решения
ШКОЛКОВО.
Готовиться с нами - ЛЕГКО!
Подтемы раздела программирование
Решаем задачу:

Ошибка.
Попробуйте повторить позже

Задача 1#88159

У медицинской компании есть N пунктов приёма биоматериалов на анализ. Все пункты расположены вдоль автомагистрали и имеют номера, соответствующие расстоянию от нулевой отметки до конкретного пункта. Известно количество пробирок, которое ежедневно принимают в каждом из пунктов.

Благодаря развитию нанотехнологий и изобретению телепортов компания, расположив в каждом пункте по одному устройству телепортации, может отправлять некоторое количество пробирок напрямую в лабораторию абсолютно бесплатно. Но так как телепортация - новая технология, пока что ещё запускать телепорты можно только раз в день, и перемещать они могут только число пробирок, являющееся членами последовательности Фибоначчи.

Поэтому компания решила телепортировать из каждого пункта максимально возможное число пробирок, а остальные поштучно доставлять в лабораторию по автомагистрали.

Стоимость перевозки биоматериалов равна произведению расстояния от пункта до лаборатории на количество пробирок. Общая стоимость перевозки за день равна сумме стоимостей перевозок из каждого пункта в лабораторию. Лабораторию расположили в одном из пунктов приёма биоматериалов таким образом, что общая стоимость доставки биоматериалов из всех пунктов минимальна.

Определите минимальную общую стоимость доставки биоматериалов из всех пунктов приёма в лабораторию.

Входные данные: Дано два входных файла (файл A и файл B), каждый из которых в первой строке содержит число            7
(1 ≤ N ≤ 10 )  – количество пунктов приёма биоматериалов. В каждой из следующих N строк находится два числа: номер пункта и количество пробирок в этом пункте (все числа натуральные, количество пробирок в каждом пункте не превышает 1000).

Пункты перечислены в порядке их расположения вдоль дороги, начиная от нулевой отметки.

В ответе укажите два числа через пробел: сначала значение искомой величины для файла A, затем – для файла B.

Вложения к задаче
Показать ответ и решение
# Файлик A

# Функция, которая вычитает максимальное подходящее число фибоначчи из числа пробирок
def fib(x):
    mx = max([i for i in fibs if x >= i])
    return x - mx

# Сначала необходимо сгенерировать числа фибоначчи до 1000
fibs = [0, 1, 1]
while fibs[-1] <= 1000:
    fibs.append(fibs[-2] + fibs[-1])

f = open(’4_27A.txt’)
n = int(f.readline())

points = []
for i in f:
    dist, cnt = map(int, i.split())
    # С поиощью нашей функции fib находим остаток нетелепортированных пробирок
    points.append([dist, fib(cnt)])

costs = []
for cur_d, cur_c in points:
    # Перебираем пункты, где можем поставить лабораторию
    sm = 0
    for dist, cnt in points:
        # Для пункта увеличиваем сумму - умножаем расстояние до лаборатории на количество контейнеров
        sm += abs(dist - cur_d) * cnt
    costs.append(sm)

print(min(costs))


# Файлик B

# Функция, которая вычитает максимальное подходящее число фибоначчи из числа пробирок
def fib(x):
    mx = max([i for i in fibs if x >= i])
    return x - mx

# Сначала необходимо сгенерировать числа фибоначчи до 1000
fibs = [0, 1, 1]
while fibs[-1] <= 1000:
                                                                                                  
                                                                                                  
    fibs.append(fibs[-2] + fibs[-1])

f = open(’4_27B.txt’)
n = int(f.readline())

# Список, в котором индекс - расстояние от нулевой отметки до этого пункта
# элементы - количества контейнеров
# Если на какой-то отметке пункта нет, там останется 0, и этот пункт не будет
# влиять на сумму

points = [0] * 10 ** 7

# Индексы первого и последнего реального пункта
start = 10 ** 10
end = -1

for i in range(n):
    # Считываем номер пункта и количество пробирок
    num, cnt = map(int, f.readline().split())
    # Вставляем на нужную отметку кол-во контейнеров
    # С поиощью нашей функции fib находим остаток нетелепортированных пробирок
    points[num] = fib(cnt)
    # Определяем крайние пункты
    if cnt > 0:
        start = min(start, num)
        end = max(end, num)

# Удаляем нулевые пункты по краям
points = points[start: end + 1]

# Изначальная сумма для 0-го пункта
sm = 0

for i in range(len(points)):
    # Умножаем кол-во контейнеров на расстояние до 0-го пункта
    sm += points[i] * i

# Если мы смещаемся на пункт вправо - расстояние до всех пунктов слева увеличится на 1,
# значит общая сумма увеличится на сумму пунктов слева

# Расстояние до всех пунктов справа уменьшится на 1,
# значит общая сумма уменьшится на сумму пунктов справа

# Сумма слева, на которую увеличится общая сумма при перемещении на один пункт вправо
left = 0
# Сумма справа, на которую уменьшится общая сумма при перемещении на один пункт вправо
                                                                                                  
                                                                                                  
right = sum(points)

current_cost = sm
# Список сумм для каждого пункта
costs = [sm]

for i in range(1, len(points)):
    # При перемещении на 1 пункт вправо из правой суммы исчезает самый перый элемент,
    # а к левой этот элемент прибавляется
    left += points[i - 1]
    right -= points[i - 1]
    # Рассчёт новой суммы, после увеличения суммы левой суммой и уменьшения правой суммой
    current_cost = current_cost + left - right
    if points[i] > 0:
        costs.append(current_cost)

print(min(costs))

Ответ: 17042792 17209100128563

Специальные программы

Все специальные программы

Программа
лояльности v2.0

Приглашай друзей в Школково и получай вознаграждение до 10%!

Крути рулетку
и выигрывай призы!

Крути рулетку и покупай курсы со скидкой, которая привязывается к вашему аккаунту.

Бесплатное онлайн-обучение

Для школьников из приграничных территорий России, проживающих в ДНР, ЛНР, Херсонской, Запорожской, Белгородской, Курской, Брянской областях и Крыму.

Налоговые вычеты

Узнай, как получить налоговый вычет при оплате обучения в «Школково».

Специальное предложение
для учителей

Бесплатный доступ к любому курсу подготовки к ЕГЭ, ОГЭ и олимпиадам от «Школково». Мы с вами делаем общее и важное дело, а потому для нас очень значимо быть чем-то полезными для учителей по всей России!

Вернём деньги за курс
за твою сотку на ЕГЭ

Сдать экзамен на сотку и получить обратно деньги за подготовку теперь вполне реально!

cyberpunkMouse
cyberpunkMouse
Рулетка
Вы можете получить скидку в рулетке!