问题描述
输入
• 𝒏个矩阵组成的矩阵链𝑼𝟏…𝒏 =< 𝑼𝟏, 𝑼𝟐, … , 𝑼𝒏 > • 矩阵链𝑼𝟏…𝒏对应的维度数分别为𝒑𝟎, 𝒑𝟏, … , 𝒑𝒏,𝑼𝒊的维度为𝒑𝒊−𝟏 × 𝒑𝒊
输出
• 找到一种加括号的方式,以确定矩阵链乘法的计算顺序,使得最小化矩阵链标量乘法的次数
-
比如: 3个矩阵相乘 U1(40,8) U2(8,30) U3(30,5)
-
结合律得到两种不同结合顺序: (U1U2)U3 或者 U1(U2U3)标量乘法次数: 15600 或 2800
解法
//规划方程式 : 从 矩阵 i 得到 矩阵 j 的最小标量乘法次数
D[i,j] = min (D[i][k] + D[K+1,j] + pi-1*pk*pj
实际代码
import org.junit.Test;
/**
* 矩阵乘法问题
* 递推式 : D[i,j] = min (D[i][k] + D[K+1,j] + pi-1*pk*pj
*
* @date 2021-06-10 21:12
*/
public class DP_MatrixMultiplication {
//测试用例,既:七个矩阵 行高,列长 U1(p0,p1) U2(p1,p2) U3(p2,p3)....
static int p[] = {2, 3, 7, 9, 5, 2, 4};
//动态数组保存 i到j的最小标量乘法次数
static int d[][];
//记录 使用括号对矩阵进行分割的位置
static int rac[][];
//矩阵的大小
static int n;
@Test
public void run0() throws Throwable {
n = p.length;
d = new int[n + 1][n + 1];
rac = new int[n + 1][n + 1];
MatrixChainMultiply();
System.out.println(d[1][n - 1]);
PrintMatrixChain(1, n - 1);
System.out.println();
}
private void MatrixChainMultiply() {
for (int l = 2; l < n; l++) {
int j = l;
for (int i = 1; i <= n - l; i++) {
d[i][j] = 0x7fffffff;
for (int k = i; k <= j - 1; k++) {
int q = d[i][k] + d[k + 1][j] + p[i - 1] * p[k] * p[j];
if (q < d[i][j]) {
d[i][j] = q;
rac[i][j] = k;
}
}
j++;
}
}
}
//递归输出 拆分形式
private void PrintMatrixChain(int i, int j) {
if (i == j) {
System.out.print("U" + i);
return;
}
System.out.print("(");
PrintMatrixChain(i, rac[i][j]);
System.out.print(")(");
PrintMatrixChain(rac[i][j] + 1, j);
System.out.print(")");
return;
}
}
输出
286
((U1)((U2)((U3)((U4)(U5)))))(U6)