一、問題描述
引出問題之前我們先來復習一下矩陣乘積的標准算法。
int ra,ca;//矩陣A的行數和列數 int rb,cb;//矩陣B的行數和列數 void matrixMultiply() { for(int i=0;i<ra;i++) { for(int j=0;j<cb;j++) { int sun=0; for(int k=0;k<=ca;k++) { sum+=a[i][k]*b[k][j]; } c[i][j]=sum; } } }
給定n個矩陣{A1,A2,…,An},其中Ai與Ai+1是可乘的,i=1,2…,n-1。如何確定計算矩陣連乘積的計算次序,使得依此次序計算矩陣連乘積需要的數乘次數最少。例如,給定三個連乘矩陣{A1,A2,A3}的維數分別是10*100,100*5和5*50,采用(A1A2)A3,乘法次數為10*100*5+10*5*50=7500次,而采用A1(A2A3),乘法次數為100*5*50+10*100*50=75000次乘法,顯然,最好的次序是(A1A2)A3,乘法次數為7500次。
加括號的方式對計算量有很大的影響,於是自然地提出矩陣連乘的最優計算次序問題,即對於給定的相繼n個矩陣,如何確定矩陣連乘的計算次序,使得依此次序計算矩陣連乘積需要的數乘次數最少。
二、問題分析
矩陣連乘也是Catalan數的一個常用的例子,關於時間復雜度的推算需要參考離散數學關於Catalan的內容。
下面考慮使用動態規划法解矩陣連乘積的最優計算次序問題。
1、分析最優解的結構
問題的最優子結構性質是該問題可以用動態規划求解的顯著特征!!!
2、建立遞歸關系
3、計算最優值
public static void matrixChain(int n) { for (int i = 1; i <= n; i++) { m[i][i] = 0; } for (int r = 2; r <= n; r++) {//i與j的差值 for (int i = 1; i <= n - r + 1; i++) { int j = i + r - 1; m[i][j] = m[i + 1][j] + p[i - 1] * p[i] * p[j]; s[i][j] = i; for (int 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; } } } } }
4、構造最優解
public static void traceback(int i, int j) { if (i == j) { System.out.printf("A%d", i); // 輸出是第幾個數據 return; } System.out.printf("("); traceback(i, s[i][j]);// 遞歸下一個數據 System.out.printf(" x "); traceback(s[i][j] + 1, j); System.out.printf(")"); }
三、總結