3、實驗二矩陣連乘
實驗內容
n個矩陣連乘,不滿足交換律,但是滿足結合律,通過不同的加括號方式,會使得需要的乘法次數不同。用動態規劃方法計算,找出最優加括號方式,使總的乘法次數最少。
解題思路
將矩陣連乘積Ai Ai +1 … Aj簡記爲A[i:j],這裏i≤j。
考察計算A[i:j]的最優計算次序。設這個計算次序在矩陣Ak和Ak+1之間將矩陣鏈斷開,i≤k<j,則其相應完全加括號方式爲(Ai Ai +1…Ak)(Ak+1 Ak+2… Aj)。
計算量:A[i:k]的計算量加上A[k+1:j]的計算量,再加上A[i:k]和A[k+1:j]相乘的計算量。
源代碼
package b矩陣連乘;
public class MatrixText {
public static void main(String agrs[]) {
int[] p = { 30, 35, 15, 5, 10, 20, 25 };
// int[] p = { 30,15,5,20,3 };
int n = p.length;
System.out.print("您輸入的矩陣爲:");
for (int i = 0; i < n - 1; i++) {
System.out.print("A" + (i + 1) + "[" + p[i] + "]" + "[" + p[i + 1] + "]" + " ");
}
System.out.println("\n");
int[][] m = new int[n][n];
int[][] s = new int[n][n];
Utils.matrixChain(p, m, s);
// 打印m矩陣
System.out.println("The m["+(n-1)+"]["+(n-1)+"] 矩陣:");
for (int i = 1; i < m.length; i++) {
for (int j = 1; j < m.length; j++) {
if (i > j) {
System.out.print("0" + "\t");
} else {
System.out.print(m[i][j] + "\t");
}
}
System.out.println();
}
System.out.println();
// 打印s矩陣
System.out.println("The s["+(n-1)+"]["+(n-1)+"] 矩陣:");
for (int i = 1; i < s.length; i++) {
for (int j = 1; j < s.length; j++) {
if (i > j) {
System.out.print("0" + "\t");
} else {
System.out.print(s[i][j] + "\t");
}
}
System.out.println();
}
System.out.println();
System.out.println("矩陣連乘加括號方式爲:");
Utils.OptimalParens(s, 1, n - 1);
}
}
package b矩陣連乘;
public class Utils {
/**
* @see 計算最優值
* @param p:各個矩陣的下標
* @param m:最優解矩陣
* @param s:最優解矩陣所取得k值的矩陣
*/
public static void matrixChain(int[] p, int[][] m, int[][] s) {
int n = p.length - 1;// 求出矩陣的個數
// 給m矩陣主對角線賦值爲0
for (int i = 1; i <= n; i++) {
m[i][i] = 0;
}
for (int r = 2; r <= n; r++)
for (int i = 1; i <= n - r + 1; i++) {
int j = i + r - 1;
// 給矩陣設置一個超大值,爲後面的比較做準備
m[i][j] = 999999999;
for (int k = i; 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和s矩陣賦值
m[i][j] = t;
s[i][j] = k;
}
}
}
}
/**
* @see 打印加括號的最優解方案
* @param s:最優解矩陣所取得k值的矩陣
* @param i:矩陣的第一個A1
* @param j:矩陣的最後一個A(n-1)
*/
public static void OptimalParens(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(" (");
// 遞歸調用
OptimalParens(s, i, s[i][j]);
OptimalParens(s, s[i][j] + 1, j);
System.out.print(") ");
}
}
}