Редактирование: Задача о порядке перемножения матриц
Внимание! Вы не авторизовались на сайте. Ваш IP-адрес будет публично видимым, если вы будете вносить любые правки. Если вы войдёте или создадите учётную запись, правки вместо этого будут связаны с вашим именем пользователя, а также у вас появятся другие преимущества.
Правка может быть отменена. Пожалуйста, просмотрите сравнение версий, чтобы убедиться, что это именно те изменения, которые вас интересуют, и нажмите «Записать страницу», чтобы изменения вступили в силу.
Текущая версия | Ваш текст | ||
Строка 41: | Строка 41: | ||
Однако, если применить этот алгоритм, то обнаружим, что он работает также медленно, как и наивный способ перебирания всех [[Правильные скобочные последовательности | скобочных последовательностей]]. Делается значительное количество ненужной работы. Например, в выше описанном алгоритме, осуществляется рекурсивный вызов, чтобы найти наилучшую стоимость для подсчета <tex>ABC</tex> и <tex>AB</tex>. Но нахождение наилучшей стоимости для подсчета <tex>ABC</tex> так же требует нахождения лучшей стоимости для <tex>AB</tex>. Так как рекурсия растет вглубь все больше и больше, то и число ненужных повторений увеличивается. Итоговая асимптотика, как было сказано выше, равняется <tex>n</tex>–ому [[Числа Каталана | числу Каталана]], да плюс вычисление для каждой [[Правильные скобочные последовательности | правильной скобочной последовательности]] ''затрат'' на перемножение (то есть <tex>O(n \cdot C_n)</tex>). Так как <tex>N</tex>-ое [[Числа Каталана | число Каталана]] равняется <tex dpi="163"> \frac{1}{n+1}{2 n \choose n} </tex> или асимптотически <tex dpi="163"> \frac{4^n}{n^{3/2}\sqrt{\pi}} </tex>, а это быстро возрастающая функциия, нам бы хотелось решение, которое работает быстрее. | Однако, если применить этот алгоритм, то обнаружим, что он работает также медленно, как и наивный способ перебирания всех [[Правильные скобочные последовательности | скобочных последовательностей]]. Делается значительное количество ненужной работы. Например, в выше описанном алгоритме, осуществляется рекурсивный вызов, чтобы найти наилучшую стоимость для подсчета <tex>ABC</tex> и <tex>AB</tex>. Но нахождение наилучшей стоимости для подсчета <tex>ABC</tex> так же требует нахождения лучшей стоимости для <tex>AB</tex>. Так как рекурсия растет вглубь все больше и больше, то и число ненужных повторений увеличивается. Итоговая асимптотика, как было сказано выше, равняется <tex>n</tex>–ому [[Числа Каталана | числу Каталана]], да плюс вычисление для каждой [[Правильные скобочные последовательности | правильной скобочной последовательности]] ''затрат'' на перемножение (то есть <tex>O(n \cdot C_n)</tex>). Так как <tex>N</tex>-ое [[Числа Каталана | число Каталана]] равняется <tex dpi="163"> \frac{1}{n+1}{2 n \choose n} </tex> или асимптотически <tex dpi="163"> \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>, что является достаточно эффективным для реальных приложений. | ||
+ | |||
+ | === Восстановление ответа === | ||
+ | С помощью вышеописанного алгоритма можно восстановить порядок, в котором нам необходимо перемножать матрицы, чтобы достичь минимального количества арифметических операций, затрачиваемых на вычисление ответа. Когда узнаем, как нам нужно разбить отрезок на два подотрезка, то при восстановлении ответа заключаем эти два подотрезка(последовательности матриц) в скобки и передаем получившийся ответ выше по рекурсии. | ||
=== Псевдокод === | === Псевдокод === | ||
− | + | <code> | |
'''int''' dp[][] <font color="green">// dp[i][j] — ответ на отрезке [i, j)</font> | '''int''' dp[][] <font color="green">// dp[i][j] — ответ на отрезке [i, j)</font> | ||
'''int''' v[] <font color="green">// Массив v[] — хранит все размеры матриц по порядку | '''int''' v[] <font color="green">// Массив v[] — хранит все размеры матриц по порядку | ||
− | // Так как у нас размеры соседних матриц по вертикали и горизонтали совпадают, то они занесены в этот массив однократно | + | // Так как у нас размеры соседних матриц по вертикали и горизонтали совпадают, то они занесены в этот массив однократно</font> |
− | + | <font color="green">// l — включая в отрезок, r — исключая из отрезка. Изначально l = 0, r = n, где n {{---}} длина последовательности</font> | |
− | '''int''' matrixChainMultiplication('''int''' l, '''int''' r) | + | '''int''' matrixChainMultiplication('''int''' l, '''int''' r): |
'''if''' dp[l][r] == -1 <font color="green">// Если значение динамики не посчитано</font> | '''if''' dp[l][r] == -1 <font color="green">// Если значение динамики не посчитано</font> | ||
'''if''' l == r - 1 | '''if''' l == r - 1 | ||
Строка 56: | Строка 62: | ||
dp[l][r] = <tex>\infty</tex> | dp[l][r] = <tex>\infty</tex> | ||
'''for''' i = l + 1 '''to''' r - 1 | '''for''' i = l + 1 '''to''' r - 1 | ||
− | dp[l][r] = min(dp[l][r], v[l] * v[i] * v[r] + matrixChainMultiplication(l, i) + matrixChainMultiplication(i, r)) | + | dp[l][r] = min(dp[l][r], v[l] * v[i] * v[r - 1] + matrixChainMultiplication(l, i) + matrixChainMultiplication(i, r)) |
'''return''' dp[l][r] | '''return''' dp[l][r] | ||
+ | </code> | ||
== См. также == | == См. также == | ||
Строка 65: | Строка 72: | ||
*[[Задача о расстановке знаков в выражении]] | *[[Задача о расстановке знаков в выражении]] | ||
*[[Задача о выводе в контекстно-свободной грамматике, алгоритм Кока-Янгера-Касами | Aлгоритм Кока-Янгера-Касами ]] | *[[Задача о выводе в контекстно-свободной грамматике, алгоритм Кока-Янгера-Касами | Aлгоритм Кока-Янгера-Касами ]] | ||
− | |||
== Источники информации == | == Источники информации == | ||