Изменения

Перейти к: навигация, поиск

Задача о порядке перемножения матриц

1332 байта убрано, 06:51, 15 декабря 2011
Нет описания правки
:''A''(''BC'') = (30×5×60) + (10×30×60) = 9000 + 18000 = 27000 операций.
Как мы видим, первый способ гораздо эффективней. Теперь стало понятно, что нам надо найти оптимальную расстановку скобок в нашем выражении из <tex>n</tex> матриц. Как бы это сделать? Мы можем перебрать все расстановки скобок (brute force), но время выполнения этого алгоритма будет расти экспоненциально от <tex>n</tex> количества матриц, так как навскидку в каждую позицию мы можем поставить открывающуюся и закрывающуюся скобку, то асимптотика будет равна ''n''­-ому [http://ru.wikipedia.org/wiki/%D0%A7%D0%B8%D1%81%D0%BB%D0%B0_%D0%9A%D0%B0%D1%82%D0%B0%D0%BB%D0%B0%D0%BD%D0%B0 числу Каталана], плюс для каждой правильной скобочной последовательности вычислить ''эффективность'' перемножения или, другими словами, <tex>O(n * C_n)</tex>. Решение данной задачи, как мы увидим — это разбить нашу задачу на подзадачи. Так же мы увидим, что с помощю решения однократного решения подзадачи и повторного использования ответа, мы сможем заметно сократить асимптотику.  
== Решение задачи ==
Например, если у нас есть четыре матрицы ''ABCD'', то мы посчитаем для (''A'')(''BCD''), (''AB'')(''CD''), и (''ABC'')(''D''), делая рекурсивные вызовы на отрезках ''ABC'', ''AB'', ''CD'', и ''BCD'', чтобы найти минимальную стоимость. Потом среди них мы выбираем лучший вариант. Так же, этот алгоритм дает не только минимальную стоимость, но и показывает наилучший способ перемножения матриц: нужно только сгрупировать тем же образом матрицы, каким дается нам минимальная стоимость.
Однако, если мы применим этот алгоритм, то мы обнаружим, что он работает также медленно, как и наивный способ перебирания всех скобочных последовательностей! Что пошло не так? Ответом на этот вопрос является то факт, что мы делаем значительное количество ненужной работы. Например, в выше описанном алгоритме, мы делали рекурсивный вызов, чтобы найти наилучшую стоимость для подсчета ''ABC'' и ''AB''. Но нахождение наилучшей стоимости для подсчета ''ABC'' так же требует нахождения лучшей стоимости для ''AB''. Так как рекурсия растет вглубь все больше и больше, то и число ненужных повторений увеличивается. Итоговая асимптотика, как было сказано выше, равняется ''n''–ому [http://ru.wikipedia.org/wiki/%D0%A7%D0%B8%D1%81%D0%BB%D0%B0_%D0%9A%D0%B0%D1%82%D0%B0%D0%BB%D0%B0%D0%BD%D0%B0 числу Каталана], да плюс вычисление для каждой правильной скобочной последовательности ''затрат'' на перемножение (то есть <tex>O(n * \cdot C_n)</tex>). <tex>N</tex>­-ое число Каталана равняется <tex> \frac{1}{n+1}{2 n \choose n} </tex> или асимптотически <tex> \frac{4^n}{n^{3/2}\sqrt{\pi}} </tex>.
=== Оптимизации динамическим программированием ===
Одно из простых решений — это ''мемоизация''. Каждый раз, когда мы считаем минимальную стоимость перемножения определенной подпоследовательности, давайте мы будем запоминать ответ. Если мы когда либо ещё раз захотим посчитать это ещё раз, то мы уже будет иметь ответ и не будем пересчитывать. Поскольку существует всего <tex>O(n^2)</tex> подотрезков, где <tex>n</tex> — это количество матриц, то память занимаемая программой будет не так велика. Можно сказать, что с помощью этого простого трюка мы уменьшили асимптотику алгоритма (перебор) с <tex>O(n * \cdot C_n)</tex> до <tex>O(n^3)</tex>, что является достаточно эффективным для реальных приложений.
=== Восстановление ответа ===
90
правок

Навигация