15.6. Оптимальный порядок перемножения матриц
Определение
Задача об оптимальном порядке перемножения матриц (matrix chain multiplication): дано $n$ матриц $A_1 \times \cdots \times A_n$, где $A_i$ имеет размер $m_{i-1} \times m_i$. Матрицы умножаются по определению: произведение матриц $m \times n$ и $n \times p$ требует $O(mnp)$ действий. Требуется выбрать порядок умножений (расстановку скобок), минимизирующий суммарное число действий.
Пусть, например, мы перемножаем матрицы размеров $100 \times 10$, $10 \times 20$ и $20 \times 2$. Порядок $(A_1 \times A_2) \times A_3$ требует $100 \cdot 10 \cdot 20 + 100 \cdot 20 \cdot 2 = 24000$ действий, а порядок $A_1 \times (A_2 \times A_3)$ — лишь $10 \cdot 20 \cdot 2 + 100 \cdot 10 \cdot 2 = 2400$.
Динамическое программирование по подотрезкам
Посмотрим на последнюю операцию умножения: мы перемножим $A_1 \times \cdots \times A_j$ и $A_{j+1} \times \cdots \times A_n$ для некоторого $j$. Операции до этого соответствуют оптимальному вычислению этих двух матриц — получаются две независимые подзадачи для подотрезков исходной последовательности.
Пусть $c[l, r]$ — минимальное количество операций, необходимое для вычисления $A_l \times \cdots \times A_r$. Начальные состояния: $c[i, i] = 0$. Переход — перебор последней пары умножаемых матриц:
$$ c[l, r] = \min_{l \leqslant i < r} \bigl(c[l, i] + c[i+1, r] + m_{l-1} \cdot m_i \cdot m_r\bigr). $$Состояния рассматриваем в порядке увеличения длины подотрезка. Получаем решение за $O(n^3)$, $O(n^2)$ дополнительной памяти.
Свойства
Восстановление ответа (оптимального порядка скобок) делается стандартными методами по массиву split. Эту задачу умеют решать за $O(n \log n)$ (Hu, Shing, 1984). Тот же подход «DP по подотрезкам» применяется в задачах об оптимальном двоичном дереве поиска и разборе контекстно-свободных грамматик. Задача тесно связана с возведением матрицы в степень.