C++動態規劃算法實現矩陣鏈乘法
問題描述:
給定n個矩陣的鏈<A1,A2,…,An>,矩陣Ai的規模為p(i-1)×p(i) (1<=i<=n),求完全括號化方案,使得計算乘積A1A2…An所需標量乘法次數最少。
動態規劃的第一步是尋找最優子結構,然後就可以利用這種子結構從子問題的最優解構造出原問題的最優解。在矩陣鏈乘法問題中,我們假設A(i)A(i+1)…A(j)的最優括號方案的分割點在A(k)和A(k+1)之間。那麼,繼續對“前綴”子鏈A(i)A(i+1)…A(k)進行括號化時,我們應該直接采用獨立求解它時所得的最優方案。
遞歸實現:
①對於i=j的情況下,顯然有m=0,不需要做任何標量乘法運算。所以,對於所有的i=1、2…n,m[i,i] = 0.
②當i < j的情況,就按照最優括號化方案的結構特征進行計算m[i,j]。假設最優括號化方案的分割點在矩陣Ak和Ak+1之間,那麼m的值就是Ai…k和Ak+1…j的代價加上兩者量程的代價的最小值。即。該公式的假設是最優分割點是已知的,但是實際上不知道。然而,k隻有j-i中情況取值。由於最優分割點k必定在i~j內取得,隻需要檢查所有可能的情況,找到最優解即可。可以得出一個遞歸公式
代碼實現【C++】
#include <iostream> using namespace std; #define N 6 #define MAXVALUE 1000000 void matrix_chain_order(int *p,int len,int m[N+1][N+1],int s[N+1][N+1]); void print_optimal_parents(int s[N+1][N+1],int i,int j); int main() { int p[N+1] = {30,35,15,5,10,20,25}; int m[N+1][N+1]={0}; int s[N+1][N+1]={0}; int i,j; matrix_chain_order(p,N+1,m,s); cout<<"m value is: "<<endl; for(i=1;i<=N;++i) { for(j=1;j<=N;++j) cout<<m[i][j]<<" "; cout<<endl; } cout<<"s value is: "<<endl; for(i=1;i<=N;++i) { for(j=1;j<=N;++j) cout<<s[i][j]<<" "; cout<<endl; } cout<<"The result is:"<<endl; print_optimal_parents(s,1,N); return 0; } void matrix_chain_order(int *p,int len,int m[N+1][N+1],int s[N+1][N+1]) { int i,j,k,t; for(i=0;i<=N;++i) m[i][i] = 0; for(t=2;t<=N;t++) //當前鏈乘矩陣的長度 { for(i=1;i<=N-t+1;i++) //從第一矩陣開始算起,計算長度為t的最少代價 { j=i+t-1;//長度為t時候的最後一個元素 m[i][j] = MAXVALUE; //初始化為最大代價 for(k=i;k<=j-1;k++) //尋找最優的k值,使得分成兩部分k在i與j-1之間 { int temp = m[i][k]+m[k+1][j] + p[i-1]*p[k]*p[j]; if(temp < m[i][j]) { m[i][j] = temp; //記錄下當前的最小代價 s[i][j] = k; //記錄當前的括號位置,即矩陣的編號 } } } } } //s中存放著括號當前的位置 void print_optimal_parents(int s[N+1][N+1],int i,int j) { if( i == j) cout<<"A"<<i; else { cout<<"("; print_optimal_parents(s,i,s[i][j]); print_optimal_parents(s,s[i][j]+1,j); cout<<")"; } }
結果
到此這篇關於C++動態規劃算法實現矩陣鏈乘法的文章就介紹到這瞭,更多相關C++矩陣鏈乘法內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!