《演算法設計與分析》學習筆記 第六章 矩陣鏈乘法問題

2021-06-27 16:24:48 字數 3238 閱讀 6746

1、矩陣鏈乘法問題的描述

給定n個矩陣構成的乙個鏈1,a2,a3,.......an>,其中i=1,2,...n,矩陣a的維數為pi-1pi,對乘積 a1a2...an 以一種最小化標量乘法次數的方式進行加全部括號。

注意:在矩陣鏈乘問題中,實際上並沒有把矩陣相乘,目的是確定乙個具有最小代價的矩陣相乘順序。找出這樣乙個結合順序使得相乘的代價最低。

2、動態規劃分析過程

動態規劃第一步是尋找乙個最優的子結構。假設現在要計算aiai+1....aj的值,計算ai...j過程當中肯定會存在某個k值(i<=ki...j分成兩部分,使得ai...j的計算量最小。分成兩個子問題ai...k和ak+1...j,需要繼續遞迴尋找這兩個子問題的最優解。

假設aiai+1....aj的乙個最優加全括號把乘積在ak和ak+1之間分開,則ai..k和ak+1..j也都是最優加全括號的。

設m[i,j]為計算機矩陣ai...j所需的標量乘法運算次數的最小值,對此計算a1..n的最小代價就是m[1,n]。現在需要來遞迴定義m[i,j],分兩種情況進行討論如下: 當

i==j

時:m[i,j] = 0

,(此時只包含乙個矩陣)

當i時:從步驟

1中需要尋找乙個k(

i≤k<

j)值,使得

m[i,j]

=min

(i≤k<j

)。設矩陣

ai的維數為

pi-1pi

,i=1,2.....n

。輸入序列為:

p=,p1,...pn>

,length[p] = n+1

。使用m[n][n]

儲存m[i,j]

的代價,

s[n][n]

儲存計算

m[i,j]

時取得最優代價處

k的值,最後可以用

s中的記錄構造乙個最優解。

動態規劃演算法的偽**如下:

dpmaxtix_chain (p)

2 n = length[p]-1;

3 for i=1 to n do

4 m[i][i] = 0;

5 for t = 2 to n do //t 是矩陣鏈的長度

6 for i=1 to n-t+1 do

7 j=i+t-1;

8 m[i][j] = maxlimit;

9 for k=i to j-1 do

10 q = m[i][k] + m[k+1][i] + qi-1qkqj;

11 if q < m[i][j] then

12 m[i][j] = q;

13 s[i][j] = k;

14 return m and s;

dpmaxtix_chain

具有迴圈巢狀,深度為

3層,執行時間為

o(n^3)

3、遞迴

int recursive_matrix_chain(int *p, int i, int j, int m[n+1][n+1], int s[n+1][n+1])

return lookup_chain(p, 1, n, m, s);

}int lookup_chain(int *p, int i, int j, int m[n+1][n+1], int s[n+1][n+1])

if(i == j)

else

}} return m[i][j];

}

我們可以根據s[i][k]和s[k+1][j]的值遞迴加括號,演算法如下
print_optimal_parens(s, i, j)

if i== j then

print "ai"

else

print "(";

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

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

print")";

採用c++語言實現這個過程,現有矩陣a

1(30×35)、a

2(35×15)

、a3(15×5)、a4(5×10)、a5(10×20)、a6(20×25),得到p=<30,35,15,5,10,20,25>。實現過程定義兩個二維陣列m和s,為了方便計算其第一行和第一列都忽略,行標和列標都是1開始。完整的程式如下所示:

#include using namespace std;

#define n 6

#define maxvalue 1000000

void matrix_chain(int *p, int len, int m[n + 1][n + 1], int s[n + 1][n + 1]);

void print_optimal_parens(int s[n + 1][n + 1], int i, int j);

int main()

; int m[n + 1][n + 1] = ;

int s[n + 1][n + 1] = ;

int i, j;

matrix_chain(p, n + 1, m, s);

cout << "m value is: " << endl;

for (i = 1; i <= n; ++i)

cout << "s value is: " << endl;

for (i = 1; i <= n; ++i)

cout << endl;

} cout << "the result is:" << endl;

print_optimal_parens(s, 1, n);

return 0;

}void matrix_chain(int *p, int len, int m[n + 1][n + 1], int s[n + 1][n + 1])

for (t = 2; t <= n; t++) //當前鏈乘矩陣的長度

}} }

}//s中存放著括號當前的位置

void print_optimal_parens(int s[n + 1][n + 1], int i, int j)

else

}

《演算法筆記》第六章學習筆記

vector是向量,可以理解成 變長陣列 使用前需要新增下列語句 include using namespace std vectorname 單獨定義 vectorarrayname arraysize 定義陣列,相當於二元陣列name index 下標訪問push back i 在vi後面新增i...

第六章 學習筆記

1.引數分為位置引數和關鍵字引數。def func positional para x,y,z passdef func keyword para kwd1 1,kwd2 4,kwd3 9 pass2.1 當有多個位置引數時,可以用乙個星號來收集引數,函式內使用這些位置引數時可以通過for 迴圈依次...

第六章學習筆記

人員中斷 程序中斷 硬體中斷 程序的陷阱錯誤 按 ctrl c 組合鍵通常會導致當前執行的程序終止。原因如下 ctrl c組合鍵會生成乙個鍵盤硬體中斷。鍵盤中斷處理程式將ctrl c組合鍵轉換為sigint 2 訊號,傳送給終端上的所有程序,並喚醒等待鍵盤輸入的程序。在核心模式下,每個程序都要檢查和...