[動態規劃] 矩陣鏈乘法問題

什麼是矩陣鏈乘法(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;
}

發佈了63 篇原創文章 · 獲贊 51 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章