Программа курса:
Разбор задачи: Минимальная стоимость билетов
Предложенный нами код:
def mincostTickets(days, costs) -> int:
day, days, last = [0] * 366, set(days), days[-1]
for i in range(1, last + 1):
if i not in days:
day[i] = day[i - 1]
else:
day[i] = min(day[i - 1] + costs[0], day[i - 7 if i>= 7 else 0] + costs[1], day[i - 30 if i >= 30 else 0] + costs[2])
return day[last]Объявление и инициализация переменных
day, days, last = [0] * 366, set(days), days[-1]
day: Это массив из 366 элементов (максимум дней в году), где каждый индекс соответствует конкретному дню года. Элементday[i]будет содержать минимальную стоимость проездных билетов для покрытия всех поездок до дняi.days: Преобразуем входной списокdaysв множество для быстрого доступа. Это упрощает проверку, является ли конкретный день днем поездки.last: Последний день поездки (days[-1]). Это нужно для оптимизации: после последнего дня поездки вычисления можно прекратить.
Основной цикл
for i in range(1, last + 1):
Здесь i — текущий день, для которого мы вычисляем минимальную стоимость. Цикл выполняется от 1 до последнего дня поездки (last).
Проверка: текущий день — день поездки
if i not in days:
day[i] = day[i - 1]
- Если текущий день не является днем поездки, то минимальная стоимость для этого дня остается такой же, как и для предыдущего (
day[i - 1]). - Это логично, так как в такие дни покупка проездного не требуется.
Вычисление минимальной стоимости
day[i] = min(
day[i - 1] + costs[0],
day[i - 7 if i >= 7 else 0] + costs[1],
day[i - 30 if i >= 30 else 0] + costs[2]
)
Если текущий день является днем поездки, то необходимо вычислить минимальную стоимость среди трех вариантов:
- 1-дневный билет: Стоимость такого билета —
costs[0], плюс минимальная стоимость для предыдущего дня (day[i - 1]). - 7-дневный билет: Стоимость такого билета —
costs[1], плюс минимальная стоимость для дня, который находится за 7 дней до текущего (day[i - 7]). Если текущий день меньше 7 (i < 7), то вместоi - 7используется 0. - 30-дневный билет: Аналогично, стоимость такого билета —
costs[2], плюс минимальная стоимость для дня за 30 дней до текущего (day[i - 30]). Если текущий день меньше 30 (i < 30), то вместоi - 30используется 0.
Возврат результата
return day[last]
После завершения цикла результатом будет минимальная стоимость проездных билетов для покрытия всех поездок. Это значение хранится в day[last], так как last — последний день поездки.
Объяснение на примере
Входные данные:
days = [1, 4, 6, 7, 8, 20]
costs = [2, 7, 15]
Ход решения:
- Инициализируем массив
dayи заполняем его нулями. Множествоdays = {1, 4, 6, 7, 8, 20}. - Проходим по каждому дню от 1 до 20 (
last = 20). - Если день не в
days, просто копируем значение из предыдущего дня. - Если день в
days, считаем минимальную стоимость проездных с учетом всех трех вариантов билетов. В итоге массив
dayбудет выглядеть примерно так:[0, 2, 2, 2, 4, 4, 6, 7, 8, 8, ..., 11]- Возвращаем
day[20], равный 11.
Вы должны Войти или Зарегистрироваться чтобы оставлять комментарии