Лекция 6: Динамическое программирование
В этой лекции вкратце изложен один из методов построения алгоритмов решения оптимизационных задач.
Динамическое программирование обычно применяется к задачам, в которых искомый ответ состоит из частей, каждый из которых в свою очередь дает оптимальное решение некоторой подзадачи. Динамическое программирование полезно, если на разных путях многократно встречаются одни и те же подзадачи; основной технический прием – запоминать решения встречающихся подзадач на случай, если та же подзадача встретится вновь.
Чтобы понять динамическое программирование, надо решать задачи. Но прежде рассмотрим пример.
Пусть надо вычислить произведение n матриц:
A1A2…An
Необходимо найти такою расстановку скобок, чтобы стоимость вычисления (количество выполненных операций) была наименьшей.
Операция умножения матриц ассоциативна, потому скобки не влияют на результат. Но скобки могут повлиять на стоимость. Поясним.
Для того, чтобы умножить матрицу A размера p×q на матрицу B размера q×r, необходимо выполнить pqr операций умножения. При этом получается матрица размера p×r.
Вычисление произведения A1A2A3 трех матриц можно выполнить двумя способами: (A1A2)A3 и A1(A2A3). Пусть размер матрицы A1 – 10×100, A2 – 100×5, A3 – 5×50. Тогда в первом случае будет выполнено (10×100×5 + 10×5×50)=7500 операций умножения, во втором случае будет выполнено (100×5×50 + 10×100×50)=75000 операций.
Можно составить алгоритм, строящий все возможные расстановки скобок, который затем выбирает лучшую расстановку. Посмотрим, сколько существует таких расстановок.
Обозначим количество расстановок скобок в выражении из n матриц через P(n). Последнее умножение может быть между k-й и (k+1)-й матрицами. До этого мы вычислили отдельно произведения k и (n-k) матриц. Таким образом,
Если получить не рекуррентный вид формулы для P(n), то будет видно, что число расстановок экспоненциально зависит от n. Такой алгоритм не позволит решить поставленную задачу в реальных условиях.
Попробуем решить задачу при помощи динамического программирования.
Расстановка скобок разрывает произведение на две части. Стоимость (количество операций умножения) вычисления исходного произведения будет равна сумме стоимостей вычисления первой части, второй части и перемножения результатов. Чем меньше будет стоимость вычисления частей, тем меньше будет общая стоимость. Следовательно, оптимальное решение задачи о перемножении матриц содержит оптимальные решения задач о перемножении ее частей. Более того, задачи о перемножении частей могут пересекаться. Например, при вычислении произведения четырех матриц A1A2A3A4, возможны такие два разбиения: (A1(A2A3))A4 и A1((A2A3)A4). Оба разбиения включают произведение (A2A3).
Чтобы решить задачу, необходимо разбить исходное произведение на две части всевозможными способами (таких способов n-1), вычислить стоимости вычисления частей и выбрать лучшее разбиение. Если какая-то часть встретится повторно, необходимо воспользоваться уже вычисленным результатом. Запишем формально.
Обозначим через m[i, j] минимальное количество умножений, необходимое для вычисления произведения части произведения Ai…Aj. В частности, стоимость вычисления всего произведения равна m[1, n]. Размер матрицы Ai равен pi-1×pi. Согласно нашим рассуждениям,
Реализуйте алгоритм на языке программирования, изложенный в разделе 2.3.
1. Задача об оптимальной триангуляции
Задан выпуклый многоугольник. Необходимо разбить его диагоналями на треугольники так, чтобы общий периметр всех треугольников был наименьший. Составьте эффективный алгоритм, решающий задачу.
Указание. Сравните с задачей об оптимальном умножении матриц.
2. 3×n + 1
Рассмотрим такой алгоритм:
1. Ввод n
2. Печать n
3. Если n=1, то конец
4. Если n нечетное, то n ← З×n+1
5. Иначе n ← n / 2
6. Перейти на шаг 2
Если на вход алгоритма задать число 22, то будет напечатана роследовательность чисел:
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.