快速計算 矩陣連乘 DP

2021-08-21 04:52:17 字數 1761 閱讀 6954

給定 n 個矩陣,其中,ai 和 ai+1(i=1,2,…,n−1)是可乘的。用加括號的方法表示矩陣連乘的次序,不同的計算次序計算量(乘法次數)是不同的,找出一種加括號的方法,使得矩陣連乘的計算量最小

例如:a1 是 m5×10 的矩陣;

a2 是 m10×100 的矩陣;

a3 是 m100×2 的矩陣。

那麼有兩種加括號的方法:

(1)(a1 a2)a3;

(2)a1(a2 a3)。

第 1 種加括號方法運算量:5×10×100+5×100×2=6000。

第 2 種加括號方法運算量:10×100×2+5×10×2=2100。

可以看出,不同的加括號辦法,矩陣乘法的運算次數可能有巨大的差別!

(一)分析問題:根據矩陣的乘法規則:am×n、an×k相乘執行乘法運算的次數為 m*n*k。

如果直接暴力窮舉所有加括號的方法,那麼加括號的所有方案是乙個卡特蘭數序列,其演算法時間複雜度為2^n,因此我們需要推理一下看能否可以用動態規劃。

(1)分析是否具有最優子結構

假設aiai+1.....aj的乘法次數是s,aiai+1....ak的乘法次數是x,ak+1ak+2.....aj的乘法次數是y,(aiai+1....ak)和(ak+1ak+2.....aj)的乘法次數是z,則s=x+y+z,只要用反證法證明一下可知:如果s是最優的,則x和y一定是最優的。

(二)建立最優值遞迴式

① :用m[i][j]表示aiai+1....aj矩陣連乘的最優值,那麼兩個子問題(aiai+1....ak)和(ak+1ak+2....aj)對應的最優值分別是m[i][k]和m[k+1][j]。

②:而(aiai+1....ak)和(ak+1ak+2....aj)的結果矩陣相乘的次數:

設am的行數為px,列數為qx,x=i,i+1,....,j。因為矩陣可乘是前乙個矩陣的列數等於下乙個矩陣的行數。

則(aiai+1…ak)的結果是乙個 pi×qk矩陣,(ak+1ak+2…aj)的結果是乙個 pk+1*qj 矩陣,qk= pk+1,兩個結果矩陣相乘的乘法次數是 pi*pk+1*qj。

③:遞迴式:

當i==j時:m[i][j]=0;

當i因為具有最優子結構性質,所以我們先求兩個矩陣的最優值,再求3個矩陣想相乘的最優值,直到n個矩陣連乘的最優值。

(三)構造最優解

上述得到的最優值只是矩陣連乘的最小的乘法次數,並不知道加括號的次序,需要從記錄表中往回追溯還原加括號,構造出最優解。用s陣列來存放各個子問題的加括號位置:

s[1][n] 表示 a1a2…an 最優解的加括號位置,即(a1a2…as[1][n])(as[1][n]+1…an),我們在遞迴構造兩個子問題(a1a2…as[1][n])、(as[1][n]+1…an)的最優解加括號位置,一直遞迴到子問題只包含乙個矩陣為止

**詳細:

#include#includeusing namespace std;

const int n = 10000;

int p[n], m[n][n], s[n][n];

int n;//矩陣個數

int matrixchain()

}} }

return m[1][5];

}//追溯法

void print(int i,int j)

cout << "(";

print(i, s[i][j]);

print(s[i][j] + 1, j);

cout << ")";

}int main()

DP 矩陣連乘

問題 給定n個矩陣,求乘法次數的最小值 1 最優子結構 乙個簡單的解決辦法是把括號放在所有可能的地方,計算每個位置的成本,並返回最小值。對於乙個長度為n的鏈,我們有n 1種方法放置第一組括號。例如,如果給定的鏈是4個矩陣。讓矩陣連為abcd,則有3種方式放第一組括號 a bcd ab cd和 abc...

矩陣連乘DP

矩陣相乘的條件 a1 a2 a1 x,y a2 y,z a3 x,z a1的列數數等於a2的行數 運算次數為x y z 對於a1,a2,an個矩陣,a1 a2 a3 a4 an 我們可以用結合律 也就是新增括號,使整個運算過程運算次數最少 演算法效率最高。維數分別為10 100 100 5 5 50...

矩陣連乘問題(dp)

題目 計算矩陣連乘積a1,a2,an,其中ai的維度為p i 1 p i 輸入規模n,p 0 p n 輸出最少乘的次數和斷點處也就是乘法順序。思路 區間dp,m i j 表示從ai到aj區間內的最少乘的次數,列舉k i用s i j 記錄每次最少次數的時候是在哪個地方斷開,即k的位置。詳見 inclu...