題目我就不贅述了,直接進入正題:
假設有矩陣1,2,3…n
核心思路是——在[1~n]之間每個位置都做一次劃分k,最小結果=先算[1-k]和[k+1-n]兩部分最小乘積+最後兩個矩陣乘積次數。
矩陣[1-n]一共要劃分n-1次,相當於一刀一刀挨個兒切過去,每個子問題同樣如此,時間複雜度為n^2。
可以看到,問題劃分為小規模時是分治的思想,但兩個小規模之間資料會重複計算好多次,因此採用動態規劃,需要中間結果和輔助標記兩個二維陣列,用空間換時間。具體**如下:
//求矩陣連乘
void
function
(int ary,
int number,
//number指有幾個矩陣
vector
int>>
& middle, vector
int>>
& flag)}}
} cout <<
"min = "
<< middle[1]
[number]
<< endl;
}//列印輔助空間
void
show_vector
(vector
int>>
& middle)
cout << endl;}}
//回溯標記陣列,列印結果
void
trackback
(int ary,
int start,
int end, vector
int>>
& flag)
if(start+
1== end)
if(flag[start]
[end]
-start >=
1) cout <<
"(";
trackback
(ary, start, flag[start]
[end]
, flag);if
(flag[start]
[end]
-start >=
1) cout <<
")";
cout <<
"*";
if(end-flag[start]
[end]-1
>=
1) cout <<
"(";
trackback
(ary, flag[start]
[end]+1
, end, flag);if
(end-flag[start]
[end]-1
>=
1) cout <<
")";
}int
main()
;//矩陣,簡單起見,6個值表示5個行列相連的矩陣
int number =
sizeof
(ary)
/sizeof
(ary[0]
)-1;
//矩陣個數
vector
int>> middle;
//臨時結果,三角形。middle[i][j]表示矩陣[i~j]相乘的最小結果
vector
int>> flag;
//輔助標記,flag[i][j]=k表示矩陣[i~j]相乘的最小結果從k處劃分——[i~k],[k+1~j]
middle.
resize
(number+1)
; flag.
resize
(number+1)
;for
(int i =
0; i < number+1;
++i)
function
(ary, number, middle, flag)
;trackback
(ary,
1, number, flag)
; cout << endl;
show_vector
(middle)
; cout << endl;
show_vector
(flag)
; cout << endl;
return0;
}
結果如下(從上往下分別是最終結果、乘積先後次序、中間結果、輔助標記):
中間結果二維陣列的填寫順序如下,構成了三角形,y軸的i到x軸的j組成了乙個範圍[i-j]:例如右上角的最終結果15125,指的是矩陣[1~6]的最小次數。
輔助標記空間及回溯過程(從右上角開始,根據標記值3分成[1-3]和[4-6]兩個區間,再根據區間找對應標記值,當區間元素<=2時無需再次回溯,直接列印結果就好。)
矩陣連乘(動態規劃)
題目描述 給定n個矩陣 a1,a2,an 其中ai與ai 1是可乘的,i 1,2 n 1。如何確定計算矩陣連乘積的計算次序,使得依此次序計算矩陣連乘積需要的數乘次數最少。例如 a1 a2 a3 a4 a5 a6 最後的結果為 a1 a2a3 a4a5 a6 最小的乘次為15125。思路 動態規劃演算...
動態規劃 矩陣連乘
includeusing namespace std 無論括號怎麼分這些連續相乘的矩陣,最後括號都可以歸結到只有兩對括號,把整個連乘的矩陣分成兩部分 0 i j m i j min i 遞迴計算矩陣連乘 int liancheng int i,int j,int p,int s return min...
動態規劃 矩陣連乘
動態規劃常常用來解決,具有最優子結構,重疊子問題的物件。最優子結構 即通過分析問題,將問題分解為多個子問題。然後每個子問題繼續分解為更多子問題。從底往上求出最有值,由最優值確定最優解。重疊子問題 在計算過程中不同子問題可能都會計算某個值。若每個子問題都去求解同乙個值,浪費時間。動態規規劃對每乙個子問...