动态规划:矩阵链乘法最优问题
矩阵链乘法是动态规划中的经典区间 DP 问题。它的重点并不是如何计算两个矩阵相乘,而是:给定一串矩阵相乘,如何加括号,才能让总计算代价最小?
如果矩阵 \(A\) 的大小是 \(a \times b\),矩阵 \(B\) 的大小是 \(b \times c\),那么 \(AB\) 的大小是 \(a \times c\),计算代价为:
这里的代价通常指的是标量乘法次数。现在我要计算多个矩阵连续相乘,假设有一串矩阵:
矩阵乘法满足结合律,因此我们可以用不同方式加括号。例如:\( (A_1A_2)A_3 \) 和 \( A_1(A_2A_3) \)。这两种方式的结果相同,但计算代价可能不同。
假设有三个矩阵:
方式一:\((A_1A_2)A_3\)
先计算 \(A_1A_2\):\( 10 \times 100 \times 5 = 5000 \);得到的矩阵大小是 \(10 \times 5\)。
然后再乘 \(A_3\):\( 10 \times 5 \times 50 = 2500 \);所以总代价是:\( 5000 + 2500 = 7500 \)
方式二:\(A_1(A_2A_3)\)
先计算 \(A_2A_3\):\( 100 \times 5 \times 50 = 25000 \);得到的矩阵大小是 \(100 \times 50\)。
然后再乘 \(A_1\):\( 10 \times 100 \times 50 = 50000 \);所以总代价是:\( 25000 + 50000 = 75000 \)
可以看到,两种加括号方式的计算结果一样,但计算代价差了十倍。
对于 \(n\) 个矩阵:
上一个矩阵的列数必须等于下一个矩阵的行数。可用一个数组 \(p\) 来表示它们的维度。
如果矩阵 \(A_i\) 的大小是 \( p_{i-1} \times p_i \),那么数组 \(p\) 的长度就是 \(n+1\)。
例如:p = [10, 100, 5, 50] 表示:
A1: 10 × 100
A2: 100 × 5
A3: 5 × 50
动态规划
矩阵链乘法具有明显的最优子结构。假设我们要求 \(A_iA_{i+1}\cdots A_j\) 的最小计算代价。最后一次乘法一定是把这一段矩阵分成两部分:
如果整个区间 \([i,j]\) 的加括号方式是最优的,那么左半部分 \([i,k]\) 和右半部分 \([k+1,j]\) 也必须分别是最优的。
令 \( dp[i][j] \) 表示计算矩阵链 \( A_iA_{i+1}\cdots A_j \) 所需要的最小代价。最终我们要求的答案就是:\( dp[1][n] \)
初始条件:如果区间里只有一个矩阵,那么不需要做任何乘法。因此:\( dp[i][i] = 0 \)
状态转移:对于区间 \([i,j]\),我们枚举最后一次乘法的分割点 \(k\)。
左半部分的最小代价是:\( dp[i][k] \),右半部分的最小代价是:\( dp[k+1][j] \)
接下来需要把这两个结果矩阵相乘。由于 \(A_i \cdots A_k\) 的结果矩阵大小是:\( p_{i-1} \times p_k \),而 \(A_{k+1} \cdots A_j\) 的结果矩阵大小是:\( p_k \times p_j \)
所以最后一次乘法的代价是:\( p_{i-1} \times p_k \times p_j \)
因此状态转移方程为:
填表顺序
这是典型的区间 dp,长区间的答案依赖短区间。所以应该按照区间长度从小到大进行计算,先枚举长度再枚举起点
代码实现
def matrix_chain_order(p):
n = len(p) - 1
dp = [[0] * (n + 1) for _ in range(n + 1)]
for length in range(2, n + 1):
for i in range(1, n - length + 2):
j = i + length - 1
dp[i][j] = float("inf")
for k in range(i, j):
cost = (
dp[i][k]
+ dp[k + 1][j]
+ p[i - 1] * p[k] * p[j]
)
dp[i][j] = min(dp[i][j], cost)
return dp[1][n]
复杂度分析
一共有 \(O(n^2)\) 个状态,因为状态由区间左右端点 \(i\) 和 \(j\) 决定。
对于每个状态 \(dp[i][j]\),需要枚举分割点 \(k\),最多需要 \(O(n)\) 次。
因此总时间复杂度是:
动态规划表 \(dp\) 的大小是 \(n \times n\),因此空间复杂度是:

浙公网安备 33010602011771号