题目描述:
给定n个矩阵{A1,A2,…,An},其中,Ai与Ai+1是可乘的,(i=1,2 ,…,n-1)。用加括号的方法表示矩阵连乘的次序,不同的计算次序计算量(乘法次数)是不同的,找出一种加括号的方法,使得矩阵连乘的次数最小。
例如:
A1是A(5*10)的方阵;
A2是A(10*100)的方阵;
A3是A(100*2)的方阵;
那么有两种加括号的方法:
(A1A2)A3;
2. A1(A2A3);
第一种方法的计算量:5*10*100+5*100*2=6000;
第二种方法的计算量:10*100*2+5*10*2=2100;
可以看出不同计算方法计算量差别很大。
/* 矩阵连乘的条件:第一个矩阵的列等于第二个矩阵的行,此时两个矩阵是可乘的;
* 多个矩阵连乘的结果矩阵,其行列等于第一个矩阵的行和最后一个矩阵的列;
* 所以矩阵Am*n和Bn*k的乘法运算次数为:m*n*k;
* m[i][j] 代表的意思是矩阵i到矩阵j连乘的最少次数
*
* 0 i = j
m[i][j] =
min{ m[i][k]+m[k+1][j] + p[i-1]p[k]p[j];} i< j i<=k < j
*/
import java.util.Arrays;
public class MatrixChain {
public static void main(String[] args) {
int[] p = { 30, 35, 15, 5, 10, 20, 25 };
int length = p.length;
int[][] m = new int[length + 1][length + 1];
int[][] s = new int[length + 1][length + 1];
for (int i = 0; i < m.length; i++) {
for (int j = 0; j < m[i].length; j++) {
m[i][j] = -100;
s[i][j] = -100;
}
}
MatrixChain(p, m, s);
for (int i = 0; i < m.length; i++) {
for (int j = 0; j < m[i].length; j++) {
System.out.printf("%6d",m[i][j]);
}
System.out.println();
}
System.out.println();
for (int i = 0; i < s.length; i++) {
for (int j = 0; j < s[i].length; j++) {
System.out.printf("%6d",s[i][j]);
}
System.out.println();
}
System.out.println();
System.out.println("乘法的最优次序:");
traceback(s, 1, p.length - 1);
}
public static void MatrixChain(int[] p, int[][] m, int[][] s) {
int lengthP = p.length;
for (int i = 1; i <= lengthP; i++) {
m[i][i] = 0;
}
// r 矩阵个数 i 左起矩阵下标 j 矩阵结束下标
for (int r = 2; r < lengthP; r++) {
for (int i = 1; i <= lengthP - r; i++) {
// 当 断开点k = i 时, i <= k < j
int j = i + r - 1;
int k = i;
m[i][j] = m[i][k] + m[k + 1][j] + p[i - 1] * p[k] * p[j];
s[i][j] = i;
for (k = i + 1; k < j; k++) {
int t = m[i][k] + m[k + 1][j] + p[i - 1] * p[k] * p[j];
if (t < m[i][j]) {
m[i][j] = t;
s[i][j] = k;
}
}
}
}
}
private static void traceback(int[][] s, int i, int j) {
if (i == j)
System.out.print("A" + i);
else if (i + 1 == j)
System.out.print(" (A" + i + " * " + " A" + j + ") ");
else {
System.out.print(" (");
traceback(s, i, s[i][j]);
traceback(s, s[i][j] + 1, j);
System.out.print(") ");
}
}
}