矩阵连乘问题
字数 1645 2025-10-31 08:19:17
矩阵连乘问题
题目描述
给定一个数组 p[],其中 p[i-1] 和 p[i] 分别表示第 i 个矩阵的行数和列数(数组长度为 n+1,表示有 n 个矩阵)。要求找出一种矩阵连乘的顺序,使得计算矩阵连乘积所需的总标量乘法次数最少,并返回这个最少的乘法次数。
例如,对于 p = [10, 20, 30, 40],表示有三个矩阵:A₁(10×20)、A₂(20×30)、A₃(30×40)。不同的计算顺序会导致不同的乘法次数:
- (A₁A₂)A₃:10×20×30 + 10×30×40 = 6000 + 12000 = 18000
- A₁(A₂A₃):20×30×40 + 10×20×40 = 24000 + 8000 = 32000
最少乘法次数为 18000。
解题过程
1. 问题分析
矩阵乘法满足结合律,但不同计算顺序的代价差异巨大。若暴力枚举所有括号化方案,时间复杂度为卡特兰数级别,不可接受。动态规划通过保存子问题解避免重复计算。
2. 定义状态
设 dp[i][j] 表示计算从第 i 个矩阵到第 j 个矩阵(A_i 到 A_j)连乘所需的最少乘法次数。
- 目标:求
dp[1][n](矩阵编号从 1 到 n)。 - 基础情况:当 i = j 时,单个矩阵无需乘法,
dp[i][i] = 0。
3. 状态转移方程
对于 i < j,考虑在位置 k(i ≤ k < j)将矩阵链拆分为 (A_i...A_k) 和 (A_{k+1}...A_j) 两部分:
- 左部分乘积代价:
dp[i][k] - 右部分乘积代价:
dp[k+1][j] - 合并两部分的代价:左部分结果矩阵(行数 p[i-1],列数 p[k])与右部分结果矩阵(行数 p[k],列数 p[j])相乘的标量乘法次数 =
p[i-1] * p[k] * p[j] - 总代价:
dp[i][k] + dp[k+1][j] + p[i-1] * p[k] * p[j]
需遍历所有可能的 k,取最小值:
dp[i][j] = min{ dp[i][k] + dp[k+1][j] + p[i-1] * p[k] * p[j] }(对 k = i, i+1, ..., j-1)
4. 计算顺序
由于 dp[i][j] 依赖于更短的子链(即区间长度 len = j-i+1 更小的情况),应按区间长度从小到大计算:
- 外层循环:长度 len 从 2 到 n(len=1 时
dp[i][i]=0) - 内层循环:起始下标 i 从 1 到 n-len+1,则 j = i+len-1
- 内层嵌套:遍历分割点 k 从 i 到 j-1
5. 示例计算
以 p = [10, 20, 30, 40](n=3)为例:
- 初始化:
dp[1][1]=0, dp[2][2]=0, dp[3][3]=0 - len=2(两个矩阵):
dp[1][2] = p[0]*p[1]*p[2] = 10*20*30 = 6000dp[2][3] = p[1]*p[2]*p[3] = 20*30*40 = 24000
- len=3(三个矩阵):
- i=1, j=3:
- k=1:
dp[1][1] + dp[2][3] + 10*20*40 = 0 + 24000 + 8000 = 32000 - k=2:
dp[1][2] + dp[3][3] + 10*30*40 = 6000 + 0 + 12000 = 18000 - 取最小值
dp[1][3] = 18000
- k=1:
- i=1, j=3:
6. 复杂度分析
- 时间复杂度:O(n³),三层循环(len、i、k)
- 空间复杂度:O(n²),存储 dp 表
7. 关键点
- 正确理解矩阵维度 p[i] 的含义:p[i-1] 是 A_i 的行数,p[i] 是 A_i 的列数。
- 按区间长度递增计算,确保子问题已求解。
- 实际问题中可额外记录分割点 k 以重构最优括号化方案。