带限制的矩阵连乘最小乘法次数问题(矩阵维度带约束版本)
题目描述
给定一个矩阵序列 \(A_1, A_2, \dots, A_n\),其中矩阵 \(A_i\) 的维度为 \(p_{i-1} \times p_i\)。现需计算矩阵连乘 \(A_1 A_2 \cdots A_n\) 的最小乘法次数,但有一个额外约束:某些相邻矩阵对不允许直接相乘(例如,\(A_i\) 和 \(A_{i+1}\) 可能被禁止相乘)。要求设计一个动态规划算法,在考虑约束的情况下求解最小乘法次数。若整个序列无法完成连乘,返回特殊值(如 \(-1\))。
解题过程
1. 问题分析
- 经典矩阵连乘问题中,任意相邻矩阵均可相乘,但本题引入了“禁止相邻相乘”的约束。
- 约束可表示为布尔矩阵
forbidden[i][j],其中forbidden[i][j] = true表示 \(A_i\) 和 \(A_j\)(相邻时)不允许直接相乘。 - 目标:在约束下找到合法的完全括号化方案,使得总乘法次数最小。
2. 状态定义
设 dp[i][j] 表示计算子序列 \(A_i A_{i+1} \cdots A_j\) 的最小乘法次数。若该子序列无法完成连乘,则 dp[i][j] = INF(无穷大)。
- 边界情况:当 \(i = j\) 时,单个矩阵无需乘法,
dp[i][i] = 0。 - 最终目标:求
dp[1][n]。
3. 状态转移方程
对于区间 [i, j],枚举分割点 \(k\)(\(i \leq k < j\)),将序列分为 \(A_i \cdots A_k\) 和 \(A_{k+1} \cdots A_j\) 两部分:
- 若
forbidden[k][k+1] = true,则 \(A_k\) 和 \(A_{k+1}\) 禁止直接相乘,不能以 \(k\) 为分割点。 - 若允许分割,则转移方程为:
\[ dp[i][j] = \min_{k \in [i, j-1]} \left\{ dp[i][k] + dp[k+1][j] + p_{i-1} \times p_k \times p_j \right\} \]
注意:即使允许以 \(k\) 分割,仍需保证左右两个子区间本身可连乘(即 dp[i][k] 和 dp[k+1][j] 均不为 INF)。
4. 算法步骤
- 初始化
dp[i][i] = 0,其余为 INF。 - 按区间长度 \(len\) 从 2 到 \(n\) 遍历:
- 遍历起点 \(i\)(从 1 到 \(n-len+1\)),终点 \(j = i+len-1\)。
- 遍历分割点 \(k\) 从 \(i\) 到 \(j-1\):
- 若
forbidden[k][k+1]为 false,则更新:
- 若
\[ dp[i][j] = \min(dp[i][j], dp[i][k] + dp[k+1][j] + p_{i-1} \times p_k \times p_j) \]
- 若
dp[1][n]为 INF,返回 -1;否则返回dp[1][n]。
5. 示例演示
假设 \(n=4\),维度数组 \(p = [2, 3, 4, 5, 6]\),约束:forbidden[2][3] = true(即 \(A_2\) 和 \(A_3\) 禁止相乘)。
- 计算
dp[1][4]时,分割点 \(k=2\) 被禁止,但 \(k=1\) 和 \(k=3\) 仍可尝试。 - 通过递归计算左右子区间,最终得到最小乘法次数为 158(具体计算略)。
6. 复杂度分析
- 时间复杂度:\(O(n^3)\),与经典矩阵连乘相同。
- 空间复杂度:\(O(n^2)\)。
7. 关键点
- 约束仅影响相邻矩阵的直接相乘,但通过分割点枚举间接规避约束。
- 需处理不可行情况(返回 -1),通过 INF 标记无效状态。