[動態規劃] 矩陣鏈乘法問題
阿新 • • 發佈:2018-01-30
計算順序 get 分享 最優 inf cat 列數 log tps
什麽是矩陣鏈乘法(Matrix Chain Multiplication)
矩陣鏈乘法問題是指給定一串矩陣序列M?M2..Mn,求至少需要進行多少次乘法運算才能求得結果
比如對於這個M?M?M?的矩陣鏈,
我們可以先計算M?M?然後結果乘以M?,也可以M?M?先算,然後乘以M?,為了表達方便,可以用括號表示計算順序。 矩陣鏈M?M?M?有兩種計算順序:((M?M?)M?)和(M?(M?M?))。 那麽不同計算順序有什麽區別? 對於((M?M?)M?): 對於(M?(M?M?)):
我們要做的就是找到讓乘法運算最少的計算順序,換言之就是找一種加括號方式,使得最後乘法運算最少
狀態轉移方程
現用 optimal(M?M?) 表示M?M?最優計算成本 cost(M?M?) 表示M?M?計算成本optimal(M?M?)=optimal(M?)+optimal(M?)+cost(M?M?)
optimal(M?)和optimal(M?)均為零;同理
optimal(M?M?)=optimal(M?)+optimal(M?)+cost(M?M?)
(M?M?M?)有兩種加括號方式, 它的最優計算成本是這兩種加括號方式中最優的那個,即:optimal(M?M?M?)=min{optimal((M?M?)M?),optimal(M?(M?M?))}
顯然,這裏說的正是動態規劃思想:我們從局部最優解出發,逐漸構造出大問題(同時局部最優解還有重疊,可以保存計算結果免去後面計算)。狀態方程已經構造出來了,下面就是實際的實現
實現
#include <iostream> #include <algorithm> #include <climits> int dp[1024][1024] = { 0 }; struct Matrix { int row; int column; }; int matrixChainCost(Matrix *ms, int n) { for (int scale = 2; scale <= n; scale++) { for (int i = 0; i <= n - scale; i++) {int j = i + scale - 1; dp[i][j] = INT_MAX; for (int k = i; k < j; k++) { dp[i][j] = std::min(dp[i][j], dp[i][k] + dp[k+1][j] + (ms[i].row*ms[k].column*ms[j].column)); } } } return dp[0][n - 1]; } int main() { int n; std::cin >> n; //n個矩陣組成的矩陣鏈 Matrix *ms = new Matrix[n]; for (int i = 0; i<n; i++) { std::cin >> ms[i].row; //第i個矩陣的行數 std::cin >> ms[i].column; //第i個矩陣的列數 } std::cout << matrixChainCost(ms, n); system("pause"); return 0; }
[動態規劃] 矩陣鏈乘法問題