Разбор задачи: Минимальная стоимость билетов

Предложенный нами код:

 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]
  1. day: Это массив из 366 элементов (максимум дней в году), где каждый индекс соответствует конкретному дню года. Элемент day[i] будет содержать минимальную стоимость проездных билетов для покрытия всех поездок до дня i.
  2. days: Преобразуем входной список days в множество для быстрого доступа. Это упрощает проверку, является ли конкретный день днем поездки.
  3. 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. 1-дневный билет: Стоимость такого билета — costs[0], плюс минимальная стоимость для предыдущего дня (day[i - 1]).
  2. 7-дневный билет: Стоимость такого билета — costs[1], плюс минимальная стоимость для дня, который находится за 7 дней до текущего (day[i - 7]). Если текущий день меньше 7 (i < 7), то вместо i - 7 используется 0.
  3. 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]

Ход решения:

  1. Инициализируем массив day и заполняем его нулями. Множество days = {1, 4, 6, 7, 8, 20}.
  2. Проходим по каждому дню от 1 до 20 (last = 20).
  3. Если день не в days, просто копируем значение из предыдущего дня.
  4. Если день в days, считаем минимальную стоимость проездных с учетом всех трех вариантов билетов.
  5. В итоге массив day будет выглядеть примерно так:

    [0, 2, 2, 2, 4, 4, 6, 7, 8, 8, ..., 11]
    
  6. Возвращаем day[20], равный 11.

 



Вы должны Войти или Зарегистрироваться чтобы оставлять комментарии