C++動(dòng)態(tài)規(guī)劃算法實(shí)現(xiàn)矩陣鏈乘法
問(wèn)題描述:
給定n個(gè)矩陣的鏈<A1,A2,…,An>,矩陣Ai的規(guī)模為p(i-1)×p(i) (1<=i<=n),求完全括號(hào)化方案,使得計(jì)算乘積A1A2…An所需標(biāo)量乘法次數(shù)最少。
動(dòng)態(tài)規(guī)劃的第一步是尋找最優(yōu)子結(jié)構(gòu),然后就可以利用這種子結(jié)構(gòu)從子問(wèn)題的最優(yōu)解構(gòu)造出原問(wèn)題的最優(yōu)解。在矩陣鏈乘法問(wèn)題中,我們假設(shè)A(i)A(i+1)…A(j)的最優(yōu)括號(hào)方案的分割點(diǎn)在A(k)和A(k+1)之間。那么,繼續(xù)對(duì)“前綴”子鏈A(i)A(i+1)…A(k)進(jìn)行括號(hào)化時(shí),我們應(yīng)該直接采用獨(dú)立求解它時(shí)所得的最優(yōu)方案。
遞歸實(shí)現(xiàn):
?、賹?duì)于i=j的情況下,顯然有m=0,不需要做任何標(biāo)量乘法運(yùn)算。所以,對(duì)于所有的i=1、2…n,m[i,i] = 0.
?、诋?dāng)i < j的情況,就按照最優(yōu)括號(hào)化方案的結(jié)構(gòu)特征進(jìn)行計(jì)算m[i,j]。假設(shè)最優(yōu)括號(hào)化方案的分割點(diǎn)在矩陣Ak和Ak+1之間,那么m的值就是Ai…k和Ak+1…j的代價(jià)加上兩者量程的代價(jià)的最小值。即。該公式的假設(shè)是最優(yōu)分割點(diǎn)是已知的,但是實(shí)際上不知道。然而,k只有j-i中情況取值。由于最優(yōu)分割點(diǎn)k必定在i~j內(nèi)取得,只需要檢查所有可能的情況,找到最優(yōu)解即可??梢缘贸鲆粋€(gè)遞歸公式
代碼實(shí)現(xiàn)【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++) //當(dāng)前鏈乘矩陣的長(zhǎng)度 { for(i=1;i<=N-t+1;i++) //從第一矩陣開始算起,計(jì)算長(zhǎng)度為t的最少代價(jià) { j=i+t-1;//長(zhǎng)度為t時(shí)候的最后一個(gè)元素 m[i][j] = MAXVALUE; //初始化為最大代價(jià) for(k=i;k<=j-1;k++) //尋找最優(yōu)的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; //記錄下當(dāng)前的最小代價(jià) s[i][j] = k; //記錄當(dāng)前的括號(hào)位置,即矩陣的編號(hào) } } } } } //s中存放著括號(hào)當(dāng)前的位置 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<<")"; } }
結(jié)果
到此這篇關(guān)于C++動(dòng)態(tài)規(guī)劃算法實(shí)現(xiàn)矩陣鏈乘法的文章就介紹到這了,更多相關(guān)C++矩陣鏈乘法內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- C++中的動(dòng)態(tài)規(guī)劃子序列問(wèn)題分析探討
- C++動(dòng)態(tài)規(guī)劃計(jì)算最大子數(shù)組
- C++動(dòng)態(tài)規(guī)劃實(shí)現(xiàn)查找最長(zhǎng)公共子序列
- C++?動(dòng)態(tài)規(guī)劃算法使用分析
- C++編輯距離(動(dòng)態(tài)規(guī)劃)
- c++動(dòng)態(tài)規(guī)劃經(jīng)典算法
- C++動(dòng)態(tài)規(guī)劃之最長(zhǎng)公子序列實(shí)例
- C++動(dòng)態(tài)規(guī)劃之背包問(wèn)題解決方法
- C++動(dòng)態(tài)規(guī)劃中關(guān)于背包問(wèn)題講解
相關(guān)文章
Linux下semop等待信號(hào)時(shí)出現(xiàn)Interrupted System Call錯(cuò)誤(EINTR)解決方法
本篇文章是對(duì)在Linux下semop等待信號(hào)時(shí)出現(xiàn)Interrupted System Call錯(cuò)誤(EINTR)的解決方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05C++:函數(shù)對(duì)象,STL提供的函數(shù)對(duì)象,函數(shù)適配器詳解
這篇文章主要介紹了C++:函數(shù)對(duì)象,STL提供的函數(shù)對(duì)象,函數(shù)適配器的使用詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-08-08C語(yǔ)言關(guān)鍵字auto與register的深入理解
本篇文章是對(duì)c語(yǔ)言關(guān)鍵字auto與register的使用進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05C語(yǔ)言 解決不用+、-、×、÷數(shù)字運(yùn)算符做加法的實(shí)現(xiàn)方法
本篇文章是對(duì)在C語(yǔ)言中解決不用+、-、×、÷數(shù)字運(yùn)算符做加法的方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05Visual?Studio?2022使用MinGW來(lái)編譯調(diào)試C/C++程序的圖文教程
這篇文章主要介紹了Visual?Studio?2022使用MinGW來(lái)編譯調(diào)試C/C++程序,以實(shí)例來(lái)簡(jiǎn)單介紹一下VS2022中如何使用MinGW來(lái)編譯、調(diào)試C/C++程序,需要的朋友可以參考下2022-08-08深入剖析C++中的struct結(jié)構(gòu)體字節(jié)對(duì)齊
要求數(shù)據(jù)內(nèi)存的起始地址的值是某個(gè)數(shù)k的倍數(shù),這就是所謂的內(nèi)存對(duì)齊,本文就來(lái)深入剖析C++中的struct結(jié)構(gòu)體字節(jié)對(duì)齊,需要的朋友可以參考下2016-05-05