6.4 Динамическое программирование
6.4.1 Понятие динамического программирования
Рекурсивная техника полезна, если задачу можно разбить на подзадачи, каж-
дая из которых решается за разумное время, т.е. суммарный размер задач будет
небольшим. Из формулы (4.1) оценки временной сложности вытекает, что если сум-
ма размеров подзадач задачи размера n равна an для некоторой постоянной a > 1, то
рекурсивный алгоритм, вероятно, имеет полиномиальную временную сложность. Но
если разбиение задачи размера n сводит ее к n задачам размера n − 1, то рекурсив-
ный алгоритм, вероятно, имеет экспоненциальную сложность. В этом случае часто
можно получить более эффективные алгоритмы с помощью специальной техники,
называемой динамическим программированием. Суть динамического програмирова-
ния основана на временном хранении в специальном массиве текущих решений на
задачах предшествующих размеров. Динамическое программирование, в сущности,
вычисляет решение всех подзадач. Вычисление идет от малых подзадач к большим,
и ответы запоминаются в таблице. Преимущество этого метода состоит в том, что
если уж подзадача решена, то ее ответ где-то хранится и никогда не вычисляется за-
ново. Рассмотрим применение метода динамического программирования на простых
примерах.
Пример 1.
1
Рассмотрим произвольную последовательность N целых чисел. Между числами
необходимо расставить знаки операций "+" или "−так что в результате получит-
ся некоторе арифметическое выражение. Это выражение всегда можно вычислить.
Пусть, например, имеется последовательность четырех чисел 17, 5, -21, 15. Суще-
ствует восемь различных выражений:
17 + 5 + -21 + 15 = 16,
17 + 5 + -21 - 15 = -14,
17 + 5 - -21 + 15 = 58,
17 + 5 - -21 - 15 = 28,
17 - 5 + -21 + 15 = 6,
17 - 5 + -21 - 15 = -24,
17 - 5 - -21 + 15 = 48,
17 - 5 - -21 - 15 = 18.
Назовем последовательность целых чисел "делимой" на K, если операции "+"
или "−" так можно разместить между этими числами, что результирующее значение
будет нацело делиться на K. В приведенном выше примере последовательность не
делится на 5, но делится на 7. Делимость на 7, например, следует из выражения
17 + 5 + −21 − 15 = −14
или из выражения
17 + 5 − −21 − 15 = 28.
Задача состоит в том, чтобы для заданного числа K проверить делимость на
него заданной последовательности. Пусть имеются следующие ограничения на зна-
чения исходных данных: 2 ≤ K ≤ 100, 1 ≤ N ≤ 10000, каждое число не больше
10000 по абсолютной величине. Очевидно, что решение задачи можно организовать
с помощью полного перебора всех вариантов простановки знаков операций между
числами и вычисления результирующей суммы. Процесс перебора всех возможных
1
1999-2000 ACM Notheastern European Regional Programming Contest
150