1. 程式人生 > >矩陣連乘問題_動態規劃

矩陣連乘問題_動態規劃

 

1)問題引導

從上面我們可以知道不同的結合方式,矩陣計算的次序數不一樣,那麼如何求這個最小次序數的劃分,即如何結合。這就是矩陣連乘問題

使用動態規劃可以解決

如下圖,如果我們使用遞迴,則會產生大量的重複計算,複雜度太高,當然使用備忘錄降低複雜度。不過更好的是使用遞推

遞推演算法分析如下:

 

 

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 void matrixChain(int n,int p[],int m[][100
],int s[][100])//遞推 4 { 5 for(int i=1;i<=n;i++){//對角線先為0 6 m[i][i]=0; 7 } 8 for(int r=2;r<=n;r++){//一共n-1個對角線 9 for(int i=1;i<=n-r+1;i++){//第i行 10 int j=i+r-1;//在該行的對角線上的點對應的j值 11 m[i][j]=m[i+1][j]+p[i-1]*p[i]*p[j];//初始化此時在i處取得最優解 12 s[i][j]=i; 13 for
(int k=i+1;k<j;k++){//如果有更小的則被替換 14 int t=m[i][k]+m[k+1][j]+p[i-1]*p[k]*p[j]; 15 if(t<m[i][j]) 16 { 17 m[i][j]=t; 18 s[i][j]=k; 19 } 20 } 21 } 22 } 23 } 24 void print_optimal_parents(int s[100][100
],int i,int j)//列印劃分的結果 25 { 26 if( i == j) 27 cout<<"A"<<i; 28 else 29 { 30 cout<<"("; 31 print_optimal_parents(s,i,s[i][j]); 32 print_optimal_parents(s,s[i][j]+1,j); 33 cout<<")"; 34 } 35 36 } 37 int main() 38 { 39 int p[1000];//每個矩陣的行數和最後一個的列數 40 int m[100][100];//儲存最優子結構 41 int s[100][100];//儲存當前結構的最優斷點 42 memset(p,0,sizeof(p)); 43 memset(m,0,sizeof(m)); 44 memset(s,0,sizeof(s)); 45 cout << "請輸入矩陣的個數"<< endl; 46 int n; 47 cin >> n; 48 cout << "請依次輸入每個矩陣的行數和最後一個矩陣的列數"<< endl; 49 for(int i=0;i<=n;i++){ 50 cin >> p[i]; 51 } 52 matrixChain(n,p,m,s); 53 cout <<"這些矩陣相乘的最少次數是"<<m[1][n]<<endl; 54 55 cout<<"結果是:"<<endl; 56 print_optimal_parents(s,1,n); 57 return 0; 58 }