Программа курса:
Разбор задачи: Возможность Отгрузки Посылок В Течение D Дней
Предложенный нами код:
def shipWithinDays(weights, days):
"""
:param weights: List[int] - список весов пакетов
:param days: int - количество дней для доставки всех пакетов
:return: int - минимальная грузоподъёмность корабля
"""
def can_ship(capacity):
# Проверяет, можно ли перевезти все пакеты с заданной грузоподъёмностью за `days` дней.
total, required_days = 0, 1
for weight in weights:
if total + weight > capacity:
required_days += 1
total = 0
total += weight
return required_days <= days
# Начальная минимальная грузоподъёмность - максимальный вес пакета
# Начальная максимальная грузоподъёмность - сумма всех весов
left, right = max(weights), sum(weights)
while left < right:
mid = (left + right) // 2
if can_ship(mid):
right = mid
else:
left = mid + 1
return leftЗаголовок функции
def shipWithinDays(weights, days):
Мы определяем функцию shipWithinDays, которая принимает два аргумента:
weights— список целых чисел, где каждый элемент обозначает вес отдельного пакета.days— целое число, обозначающее количество дней, за которое необходимо доставить все пакеты.
Вспомогательная функция can_ship
def can_ship(capacity):
total, required_days = 0, 1
for weight in weights:
if total + weight > capacity:
required_days += 1
total = 0
total += weight
return required_days <= days
Эта вспомогательная функция проверяет, можно ли перевезти все пакеты с заданной грузоподъёмностью capacity за days дней.
- Мы проходим по каждому пакету.
- Если текущий пакет вместе с уже загруженными превышает текущую грузоподъёмность
capacity, то увеличиваем количество необходимых дней (required_days) и начинаем новую "погрузку" с текущего пакета. - Если общее число дней, требуемых для перевозки всех пакетов, не превышает
days, функция возвращаетTrue.
Пример: Если weights = [3, 2, 2, 4] и capacity = 6, то:
- В первый день: загружаем
[3, 2](общий вес 5, меньше 6). - Во второй день: загружаем
[2, 4](общий вес 6, равно 6). Итого, требуется 2 дня.
Инициализация границ поиска
left, right = max(weights), sum(weights)
Мы используем бинарный поиск, чтобы найти минимальную грузоподъёмность.
left— минимально возможная грузоподъёмность (максимальный вес одного пакета).right— максимально возможная грузоподъёмность (сумма всех весов, если перевозить все пакеты за 1 день).
Бинарный поиск
while left < right:
mid = (left + right) // 2
if can_ship(mid):
right = mid
else:
left = mid + 1
Мы выполняем бинарный поиск, чтобы найти минимальную грузоподъёмность:
- Находим середину диапазона (
mid). - Проверяем, можно ли перевезти все пакеты за
daysдней с грузоподъёмностьюmid, вызвав функциюcan_ship(mid). - Если это возможно, уменьшаем правую границу (
right = mid), так как ищем минимальную возможную грузоподъёмность. - Если это невозможно, увеличиваем левую границу (
left = mid + 1).
Идея: Мы сужаем диапазон поиска до тех пор, пока left и right не совпадут.
Результат
return left
После завершения бинарного поиска left содержит минимальную грузоподъёмность, при которой все пакеты можно доставить за days дней.
Пример работы алгоритма
Входные данные:
weights = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
days = 5
- Инициализация:
left = max(weights) = 10right = sum(weights) = 55 - Первый шаг бинарного поиска:
mid = (10 + 55) // 2 = 32
Проверяемcan_ship(32).- День 1:
[1, 2, 3, 4, 5, 6](вес 21) - День 2:
[7, 8](вес 15) - День 3:
[9, 10](вес 19)
Ответ:True(требуется 3 дня ≤ 5).
Сужаем диапазон:right = 32.
- День 1:
- Второй шаг бинарного поиска:
mid = (10 + 32) // 2 = 21
Проверяемcan_ship(21).- День 1:
[1, 2, 3, 4, 5](вес 15) - День 2:
[6, 7](вес 13) - День 3:
[8](вес 8) - День 4:
[9, 10](вес 19)
Ответ:True.
Сужаем диапазон:right = 21.
- День 1:
- Третий шаг бинарного поиска:
mid = (10 + 21) // 2 = 15
Проверяемcan_ship(15).- День 1:
[1, 2, 3, 4, 5](вес 15) - День 2:
[6, 7](вес 13) - День 3:
[8](вес 8) - День 4:
[9](вес 9) - День 5:
[10](вес 10)
Ответ:True.
Сужаем диапазон:right = 15.
- День 1:
- Четвертый шаг бинарного поиска:
mid = (10 + 15) // 2 = 12
Проверяемcan_ship(12).- День 1:
[1, 2, 3, 4](вес 10) - День 2:
[5, 6](вес 11) - День 3:
[7, 8](вес 15) - День 4:
[9](вес 9) - День 5:
[10](вес 10)
Ответ:False(требуется 6 дней > 5).
Расширяем диапазон:left = 13.
- День 1:
- Пятый шаг бинарного поиска:
mid = (13 + 15) // 2 = 14
Проверяемcan_ship(14).
Ответ:False.
Расширяем диапазон:left = 15. - Завершение:
left == right == 15.
Ответ: минимальная грузоподъёмность — 15.
Вы должны Войти или Зарегистрироваться чтобы оставлять комментарии