矩阵连乘方案
约 449 字大约 2 分钟
2024-11-03
传入一个一维数组,代表矩阵
思想
构建二维数组 m[n + 1] [n+1],用于动态规划查表
对于左上角到右下角的对角线初始化为0,因为对角线相当于自身与自身,长度为 1 的矩阵链不需要乘法
重要前提
假设 A:15 * 45, B:45 * 23, C: 23 * 12, D:12 * 32
那么假设在 B 与 C 处断开,即(A * B) * (C * D),那么计算次数为(A 与 B 相乘的次数) + (C 与 D 相乘的次数)+ (A 的行 * C 的行 * D 的列,即 15 * 23 * 32)
一段嵌套循环
- r:表示矩阵链的长度,[2, n]
- i:表示矩阵链的起始位置,[1, n + 1]
- j:表示矩阵链的结束位置,j = r + i - 1
- 在 i 和 i+1 处断开,并记录
- 在该链长范围下,遍历各种断开点。k:表示可能的断开位置,[i + 1, j),若出现更好的断开位置,则更新先前记录的断开位置
- i:表示矩阵链的起始位置,[1, n + 1]
代码
void dpMatrix(int[] matrix) {
int n = matrix.length - 1;
int[][] m = new int[n + 1][n + 1];
int[][] s = new int[n + 1][n + 1];
// 初始化边界
for (int i = 0; i <= n; ++i) {
m[i][i] = 0;
}
for (int r = 2; r <= n; ++r) {
for (int i = 1; i <= n + 1 - r; ++i) {
int j = r + i - 1;
// 在 i 与 i+1 处分隔
m[i][j] = m[i + 1][j] + matrix[i - 1] * matrix[i] * matrix[j];
s[i][j] = i;
for (int k = i + 1; k < j; ++k) {
int temp = m[i][k] + m[k + 1][j] + matrix[i - 1] * matrix[k] * matrix[j];
if (temp < m[i][j]) {
m[i][j] = temp;
s[i][j] = k;
}
}
}
}
System.out.println("最小计算量: " + m[1][matrix.length - 1]);
System.out.print("最佳分隔位置为: ");
print(s, 1, matrix.length - 1);
}
void print(int[][] s, int i, int j) {
if (i == j) {
System.out.print("A" + i);
} else {
System.out.print("(");
print(s, i, s[i][j]);
print(s, s[i][j] + 1, j);
System.out.print(")");
}
}