Динамическое программирование: основы
Динамическое программирование: состояния, переходы, база — лестница и максимальный подотрезок.
Динамическое программирование (ДП) — метод решения задач, которые разбиваются на перекрывающиеся подзадачи: каждую подзадачу решаем ОДИН раз и запоминаем ответ.
Рецепт из трёх вопросов:
1. Состояние: что такое dp[i]? (словами, точно!)
2. Переходы: как dp[i] выражается через меньшие состояния?
3. База: чему равны самые маленькие состояния?
Hello-world ДП — лестница: вы стоите внизу лестницы из n ступеней и шагаете на 1 или 2 ступени. Сколько способов подняться?
• dp[i] — число способов добраться до ступени i;
• на ступень i приходят со ступени i-1 или i-2, значит dp[i] = dp[i-1] + dp[i-2];
• база: dp[0] = 1 (стоим внизу), dp[1] = 1.
Лестница. Введите n до 80, например: 10
Для n = 10 ответ 89 — это числа Фибоначчи, выросшие из задачи сами собой.
Два стиля записи ДП:
• табличный (как выше): заполняем массив от базы вверх;
• мемоизация: пишем рекурсию и кешируем ответы. Что удобнее — дело вкуса, сложность одинакова.
Вторая классика — максимальная сумма подотрезка (алгоритм Кадане). Состояние: dp[i] — максимальная сумма подотрезка, ЗАКАНЧИВАЮЩЕГОСЯ в i. Переход: либо продолжаем предыдущий отрезок, либо начинаем новый с a[i].
Максимальный подотрезок. Введите: 8, затем -2 1 -3 4 -1 2 1 -5
Ответ на примере: 6 (подотрезок 4 -1 2 1). Заметьте: dp-массив здесь схлопнулся в одну переменную cur — так часто бывает, когда переход смотрит только на предыдущее состояние.
Задание: решите «лестницу», если наступать на некоторые ступени запрещено (dp[i] = 0 для запрещённых). И подумайте, как изменится задача при шагах 1, 2 и 3.
Отметьте урок пройденным — Уровень 4 завершён. Впереди продвинутое ДП!