Вступить в клуб →
сложнаявопросРекурсия и динамическое программирование

Рюкзак 0/1 на одномерном массиве: почему предмет берётся дважды

Классический рюкзак 0/1: каждый предмет можно взять не более одного раза.

def knapsack(weights, values, cap):
    dp = [0] * (cap + 1)
    for w, v in zip(weights, values):
        for c in range(w, cap + 1):
            dp[c] = max(dp[c], dp[c - w] + v)
    return dp[cap]

Вызов knapsack([3], [5], 9) возвращает 15, хотя предмет всего один и правильный ответ 5. Где ошибка?

  • Внутренний цикл идёт по возрастанию, поэтому предмет берётся повторно: нужен range(cap, w - 1, -1)
  • Ошибка в zip: он молча обрезает списки разной длины, из-за чего предмет обрабатывается несколько раз
  • Массив dp надо инициализировать минус бесконечностью везде, кроме dp[0], иначе максимум берётся из мусора
  • Одномерный dp для рюкзака 0/1 непригоден в принципе: нужна двумерная таблица по предметам и вместимости

🔒 Проверка ответа — для участников клуба

  • Проверка ответа
  • Подсказка, если застряли
  • Разбор с объяснением, почему так
  • Прогресс по всем задачам и виртуальные собеседования
Зарегистрироваться →

Регистрация занимает минуту

Другие задачи раздела