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 訊號,傳送給終端上的所有程序,並喚醒等待鍵盤輸入的程序。在核心模式下,每個程序都要檢查和...