
- •Глава 4. Эффективность алгоритмов.
- •4.1. Сложность алгоритма
- •4.1.1. Машины рам и рам*
- •1.2. Оценки сложности алгоритмов
- •1.3 Язык Упрощенный Алгол.
- •4.2. Методы повышения эффективности алгоритмов
- •4.2.1. Рекурсия.
- •4.2.2. Прием “разделяй и властвуй”.
- •4.2.3 Принцип балансировки
- •4.2.4 Динамическое программирование
- •4.3. Заключение
4.2.4 Динамическое программирование
Рекурсивная техника полезна, если задачу можно разбить на подзадачи за разумное время, а суммарный размер подзадач будет небольшим. Из теоремы 4.1 вытекает, что если сумма размеров подзадач равна an для некоторой постоянной а>0, то рекурсивный алгоритм, вероятно, имеет полиномиальную временную сложность.
Но если очевидное разбиение задачи размера n сводит ее к n задачам размера n-1, то рекурсивный алгоритм, вероятно, имеет экспоненциальную сложность. В этом случае часто можно получить более эффективные алгоритмы с помощью табличной техники, называемой динамическим программированием.
В сущности, при динамическом программировании вычисляется решение для всех подзадач. Вычисление идет от малых подзадач к большим, и ответы запоминаются в таблице. Преимущество этого метода состоит в том, что раз уж задача решена, ее ответ где-то хранится и никогда не вычисляется заново.
Рассмотрим эту технику на примере вычисления произведения n матриц М=М1 x М2 x...x Мk , где Mi-матрица с ri-1 строками и ri столбцами. Порядок, в котором эти матрицы перемножаются, может существенно сказаться на общем числе операций, требуемых для вычисления М, независимо от алгоритма, применяемого для умножения матриц.
Пример 4.1.
Будем считать, что умножение (р x q)-матрицы на (q x r)-матрицу требует pqr операций, и рассмотрим произведение (в квадратных скобках указаны размерности матриц).
М= М1 x М2 x М3 x М4
[10 x 20] [20 x 50] [50 x 1] [1 x 100]
Если вычислять М в порядке М1x (М2x(М3xМ4)), то потребуется 125000 операций, тогда как вычисления в порядке (М1x(М2xМ3))xМ4 занимает лишь 2200 операций.
Процесс перебора всех порядков, в которых можно вычислить рассматриваемое произведение n матриц, с целью минимизации числа операций имеет экспоненциальную сложность, что при больших n практически неприемлемо. Однако динамическое программирование приводит к алгоритму сложности О(n3).
4.3. Заключение
При разработке эффективных алгоритмов необходимо использовать как структуры высокого уровня (списки, очереди, стеки ), так и мощную технику рекурсии и динамического программирования. Важными являются приемы общего вида “разделяй и властвуй” и “балансировка”. Существуют и другие методы повышения эффективности алгоритмов [...]. Разработчик алгоритмов должен изучить задачу с разных точек зрения, пока не убедится, что получил алгоритм, наиболее подходящий для его целей.