矩阵链乘法问题的 Python 实现(《算法导论》)
思路
递归公式
$$
m[i, j] =
\left{
\begin{matrix}
\begin{align}
& 0 & if \quad i = j \
& min{m[i, k] + m[k + 1, j] + p_{i - 1} p_k p_j} & if \quad i < j \
\end{align}
\end{matrix}
\right.
$$
伪码
关于伪码的说明。
m[i, j] 表示计算矩阵 $A_{i..j}$
的所需标量乘法次数的最小值。而 $A_{i..j}(i \leqslant) j$
表示的是 $A_iA_{i + 1} \cdots A_j$
乘积的结果矩阵。s[i, j] 表示记录最优值 m[i, j] 对应的分割点 k,我们可以依赖最终的 s 表来构造最优解。
还有一个注意点,即 $A_i = p_{i - 1} \times p_i$
。
Python 代码
1 |
|
测试的输出:
1 |
|
说明
这个算法初看时不容易理解,但是跟着书上的思路,仔细地走上一遍,最终理解这个算法的思想是不困难的。
但是,在实现代码的过程中,也没有想象中那样顺利。主要原因是数组索引的问题。书中的数组索引有的是以 1 作为起始索引,有的是以 0 作为起始索引,而我在使用 Python 实现的过程中,全部是以 0 作为起始索引(这样主要是为了不浪费空间)。这样一来,就很可能产生一些索引的对应问题。遂,将索引对应的关系记录如下
m[i][j]
:对应书中的m[i + 1, j + 1]
,表示计算矩阵$A_{i + 1..j + 1}$
所需标量乘法次数的最小值。关于定义,书中是m[1..n, 1..n]
,而代码中是m[0..n - 1][0..n - 1]
。s[i][j]
:对应书中的s[i + 1, j + 2]
,表示最优值m[i + 1][j + 2]
对应的分割点 k。关于定义,书中是s[1..n - 1, 2..n]
,而代码中是s[0..n - 1][0..n - 1]
,因此,这也导致了在代码中,与m[i][j]
对应的最优分割点是s[i][j - 1]
。
矩阵链乘法问题的 Python 实现(《算法导论》)
http://fanlumaster.github.io/2021/05/03/矩阵链乘法问题的-Python-实现(《算法导论》)/