矩阵链乘法的动态规划算法
- 定义问题
-
给定矩阵链 (A1,A2,...,An)( A_1, A_2, \dots, A_n )(A1,A2,...,An),其中 AiA_iAi 的维度为 (pi−1×pi)( p_{i-1} \times p_i )(pi−1×pi)。
-
目标是找到计算 (A1A2...An)( A_1A_2 \dots A_n )(A1A2...An) 的最优顺序,使得所需的乘法次数最少。
- 动态规划表格
-
定义 m[i][j]m[i][j]m[i][j] 表示子链 (Ai...Aj)( A_i \dots A_j )(Ai...Aj) 的最小乘法次数。
-
表格 mmm 的大小为 n×nn \times nn×n,其中 m[i][j]m[i][j]m[i][j] 专门对应从 AiA_iAi 到 AjA_jAj 的最小乘法次数。
- 链长 lll 的作用
-
链长 lll 代表子链的长度,取值从 2 到 nnn 逐步递增。
-
链长 l=2l=2l=2 对应两个矩阵相乘,l=3l=3l=3 对应三个矩阵相乘,以此类推直至覆盖完整矩阵链。
- 表格填充步骤
4.1 初始化
当 i=ji = ji=j 时,子链仅包含一个矩阵,无需进行乘法运算,因此乘法次数为 0,即 m[i][i]=0m[i][i] = 0m[i][i]=0。
4.2 按链长递增填充表格
-
外层循环:链长 lll 从 2 遍历至 nnn(覆盖所有可能的子链长度)。
-
中层循环:遍历所有可能的起始位置 iii,取值范围为 111 到 n−l+1n - l + 1n−l+1。
-
计算结束位置:由起始位置 iii 和链长 lll 可得,j=i+l−1j = i + l - 1j=i+l−1。
-
内层循环:尝试所有可能的分割点 kkk(i≤k<ji \leq k < ji≤k<j),通过以下公式计算 m[i][j]m[i][j]m[i][j] 的最小值:
m[i][j]=mini≤k<j(m[i][k]+m[k+1][j]+pi−1pkpj)m[i][j] = \min_{i \leq k < j} \left( m[i][k] + m[k+1][j] + p_{i-1}p_k p_j \right)m[i][j]=i≤k<jmin(m[i][k]+m[k+1][j]+pi−1pkpj)
4.3 最终结果
表格中的 m[1][n]m[1][n]m[1][n] 即为整个矩阵链 A1A2...AnA_1A_2 \dots A_nA1A2...An 的最小乘法次数。
- 链长 lll 的具体计算过程
假设矩阵链长度 n=4n = 4n=4,矩阵维度序列为 p=[p0,p1,p2,p3,p4]p = [p_0, p_1, p_2, p_3, p_4]p=[p0,p1,p2,p3,p4],以下是链长 lll 从 2 到 4 的完整计算过程:
5.1 链长 l=2l = 2l=2(两个矩阵相乘)
计算所有相邻矩阵对的最小乘法次数(仅一种分割方式,无需比较):
-
m[1][2]=p0p1p2m[1][2] = p_0 p_1 p_2m[1][2]=p0p1p2
-
m[2][3]=p1p2p3m[2][3] = p_1 p_2 p_3m[2][3]=p1p2p3
-
m[3][4]=p2p3p4m[3][4] = p_2 p_3 p_4m[3][4]=p2p3p4
5.2 链长 l=3l = 3l=3(三个矩阵相乘)
每个子链有两种分割方式,取计算结果的最小值:
m[1][3]=min(m[1][1]+m[2][3]+p0p1p3,m[1][2]+m[3][3]+p0p2p3)m[1][3] = \min(m[1][1] + m[2][3] + p_0 p_1 p_3, m[1][2] + m[3][3] + p_0 p_2 p_3)m[1][3]=min(m[1][1]+m[2][3]+p0p1p3,m[1][2]+m[3][3]+p0p2p3)
m[2][4]=min(m[2][2]+m[3][4]+p1p2p4,m[2][3]+m[4][4]+p1p3p4)m[2][4] = \min(m[2][2] + m[3][4] + p_1 p_2 p_4, m[2][3] + m[4][4] + p_1 p_3 p_4)m[2][4]=min(m[2][2]+m[3][4]+p1p2p4,m[2][3]+m[4][4]+p1p3p4)
5.3 链长 l=4l = 4l=4(完整矩阵链)
整个矩阵链有三种分割方式,取计算结果的最小值:
m[1][4]=min(m[1][1]+m[2][4]+p0p1p4,m[1][2]+m[3][4]+p0p2p4,m[1][3]+m[4][4]+p0p3p4)m[1][4] = \min( m[1][1] + m[2][4] + p_0 p_1 p_4, m[1][2] + m[3][4] + p_0 p_2 p_4, m[1][3] + m[4][4] + p_0 p_3 p_4 )m[1][4]=min(m[1][1]+m[2][4]+p0p1p4,m[1][2]+m[3][4]+p0p2p4,m[1][3]+m[4][4]+p0p3p4)
- 时间复杂度分析
6.1 子问题数量
动态规划表格 mmm 的规模为 n×nn \times nn×n,因此子问题总数为 O(n2)O(n^2)O(n2)。
6.2 每个子问题的计算量
对于子链 m[i][j]m[i][j]m[i][j],分割点 kkk 的取值范围为 i≤k<ji \leq k < ji≤k<j,共 O(j−i)O(j - i)O(j−i) 种可能,即每个子问题的计算量为 O(n)O(n)O(n)。
6.3 总计算量
算法通过三层循环实现,总时间复杂度为 O(n3)O(n^3)O(n3),各层循环的时间复杂度如下:
-
外层循环:链长 lll 从 2 到 nnn,共 O(n)O(n)O(n) 次。
-
中层循环:起始位置 iii 从 1 到 n−l+1n - l + 1n−l+1,共 O(n)O(n)O(n) 次。
-
内层循环:分割点 kkk 从 iii 到 j−1j - 1j−1,共 O(n)O(n)O(n) 次。
- 总结
矩阵链乘法的动态规划算法核心是通过链长 lll 控制子问题规模,按子链长度从小到大的顺序逐步填充动态规划表格 m[i][j]m[i][j]m[i][j],最终通过 m[1][n]m[1][n]m[1][n] 得到完整矩阵链的最小乘法次数。该算法的时间复杂度为 O(n3)O(n^3)O(n3),其中 nnn 为矩阵链中矩阵的个数。