amming II
Michael Tsai 2011/3/25
上課 !
假如我們有點記性的話…
空間換取時間
做過的事情就不要再做
“ 記得結果”就好 : 填表與查表
Dynamic programming: 這裡的 programm ing 指填表 , 不是寫程式
當
所有不同的 subprogram 數目是 polynomia l, 及
解掉 subprogram 的時間也是 polynomial, dynamic programming 方法可以在 pol ynomial time 內完成
Dynamic programming 的做法
Top-down with memoization
還是用遞迴的方式來做
但是每次做之前就先檢查是不是做過一樣的
如果沒做過就遞迴下去 , 但是要記錄結果
如果做過就用查表取得之前的結果
Bottom-up method
把所有的 subprogram 從小排到大
然後從小排到大來解
解一個 subproblem 時候 , 所有它所需要的 subsub problem 都已經被解完了
請問哪一個快 ?
課本 p.365 有答案 .
Cut-Rod v0.1 beta (Top-down)
Memoized_Cut_Rod(p,n)
let r[0..n] be a new array for i=0 to n
r[i]=-
return Memoized_Cut_Rod_Aux(p,n,r)
Memoized_Cut_Rod_Aux(p,n,r) if
return r[n]
if n==0 q=0
else q=-
for i=1 to n
q=max(q,p[i]+Memoized_Cut_Rod_Aux(p,n-i,r)) r[n]=q
return q
Cut-Rod v0.1 gamma (Bottom-up)
Bottom_Up_Cut_Rod(p,n)
let r[0..n] be a new array r[0]=0
for j=1 to n q=-
for i=1 to j
q=max(q,p[i]+r[j-i]) r[j]=q
return r[n]
Θ (�2)
Subproblem graphs
4
3
2 1 0
1 0 0
0
2 1 0
1 0 0
0
4
3
2 1 0 Bottom-up method: Reverse
Topological Sort
Subproblem x 必須要考慮 subproblem 之 optimal solution <x,y>
Top-down method: Depth First Search
Subproblem graphs
Subproblem graph 的大小讓我們可以估計 dyna mic programming 演算法的執行時間
大小 ?
我們指和 .
= 有幾個要解的 subproblem ( 因為有記結果 , 所以一個 subproblem 只要做一次 )
= 每個 subproblem 需要幾個比它小的 subprobl em 的結果
大致的估計 : 和和成線性
最後的小問題
剛剛的程式只把可以拿多少錢算出來
沒有真的印出要怎麼切
如何解決 ?
用另外一個陣列 ( 大小 ) 紀錄 optimal soluti on 應該切的大小 .
最後依序印出結果即可 .
課本 p. 369 有解答 .
連串矩陣相乘問題
Matrix multiplication is associative.
以上算出來答案都一樣
�1
�2 �3 �4 …… ��
題目 : 求矩陣相乘之解 .
.cols=.rows
and are compatible.
連串矩陣相乘問題
Matrix-Multiply(A,B) if A.columns != B.rows
error “incompatible dimensions”
else let C be a new A.rows x B.cols matrix for i=1 to A.rows
for j=1 to B.cols
=0
for k=1 to A.cols return C
主要花費時間在這邊 !
�
�
p q
共花費 pqr 次乘法的時間
看一個例子
花費之乘法數目 =
花費之乘法數目 =
差十倍 !!
10
100 5 100
5
50
連串矩陣相乘問題 - 正式版
給一連串的矩陣 , 其中矩陣的大小為 (, 找 出一種乘法可以使計算時的乘法數目最少
沒有真的要算結果 , 而只是找出能最快算出結 果的方法 .
因為算”怎麼算比較快”多花的時間 , 比”用 爛方法直接算”多花的時間少很多
暴力法有多暴力
全部到底有幾種算法呢 ?
用遞迴定義 :
上學期有講過喔 ~
P(n) 之解為 Catalan numbers, , or is also
神父 , 我有罪 .
� (� )=
{
� =1� − 1∑
� (�) � (� −�)1if
if .
假設先這樣分 :
所以不耍暴力了 .
使用 dynamic programming
正規步驟 :
1. 找出最佳解的”結構”
2. 使用遞迴來定義最佳解的花費
3. 計算最佳解的花費
4. 使用已經計算的資訊來構築最佳解
找出最佳解的”結構”
總花費 = 的花費 + 的花費 + 把和乘起來的花費
最佳解的結構 : 假設有的最佳解 , 此一方法為在 k 切一刀 . 則在此最佳解中 , 的相乘方法一定是的最佳相乘方法
假設不是最佳解 , 則我們可以在中把換成更好的方法 , 則 可以找到一個更好的的相乘方法 矛盾 .
子問題的最佳解可以導出大問題的最佳解 !
最後結論 : 分成兩個子問題 , 並嘗試所有可以切分的地方 (k 值 )
�
��
� +1… �
�
�
�+1�
� +2… �
��≤ �
�≤ �< �
在 k 切一刀
使用遞迴來定義最佳解的花費
遞迴定義 : 使用子問題最佳解的 cost 來定義大 問題最佳解的 cost
定義 : 為所需花的最少乘法數
所花乘法數 =
��..�
��+1.. �
.rows=
.cols=
.rows=
.cols=
使用遞迴來定義最佳解的花費
但是我們不知道最佳解中的 k 的值
因此我們必須找所有
最後版本 :
�[� , �]=
{
� ≤ �< �min {�[� , �]+�[� +1, �0 ]+�� −1��� �}if
if .
計算最佳解的花費
純 recursive 解法 : exponential time
使用前面教的 Bottom-up 填表方法 : 每個不同 的 subprogram 僅需解 1 次
有幾個不同的問題 ?
, 幾個 i 和 j 的組合 ?
答案 :
�≠ �
�= �
計算最佳解的花費
如何決定填表的順序呢 ? ( 這次有 i,j 兩個變 數 )
�[� , �]=
{
� ≤ �< �min {�[� , �]+�[� +1, �0 ]+�� −1��� �}if
if . 個矩陣相乘
個矩陣相乘
都小於個
我們可以把 j-i+1( 也就是要相乘的 matrix 個數 ) 當作 problem size 的定義
n=p.length-1
let m[1..n,1..n] and s[1..n-1,2..n] be new tables for i=1 to n
m[i,i]=0
for l=2 to n
for i=1 to n-l+1 j=i+l-1
m[i,j]=
for k=i to j-1
q=m[i,k]+m[k+1,j]+
if q<m[i,j]
m[i,j]=q s[i,j]=k
return m and s
大 problem 的解只會用到小 problem 的解 . 因此慢慢往上長 . 邊界條件先設好 .
把同樣 problem size 的所有 i,j 組合都依 序做過
使用遞迴式找出最佳切點 k
Θ(� 3)
計算最佳解的花費
用一個例子來 trace code 比較快
Matrix Dimensi
on 30 x
35 35 x 15 15 x 5 5 x 10 10 x 20 20 x 25 Matrix
Dimensi
on 30 x
35 35 x 15 15 x 5 5 x 10 10 x 20 20 x 25
使用已經計算的資訊來構築最 佳解
前面只印出了花費 , 不是真正的解
怎麼乘才是最後的解
使用 s 陣列的資訊
使用已經計算的資訊來構築最佳解
Print-Optimal-Parens(s,i,j) if i==j
print else
print “(“
Print-Optimal-Parens(s,i,s[i,j]) Print-Optimal-Parens(s,s[i,j]+1,j) print “)”
看了兩個例子以後…
問 : 一個問題要有什麼要件才能使用 dynamic programming?
答 :
1. Optimal substructure
2. Overlapping Subproblems
什麼是 Optimal substructure?
Definition: A problem exhibi ts optimal substructure if a n optimal solution to the pr oblem contains within it opt imal solutions to subproblem s.
怎麼尋找 optimal substructur e 呢 ?
怎麼尋找 optimal substructure 呢 ?
1.
要得到問題的解答有許多選擇 ( 砍在哪邊 , 切在 哪邊 ), 而做這個選擇之後 , 我們有一些 subpro blem 要解決 .
2.
我們假設對於一個問題 , 我們可以找到那個選擇
3.
知道這個選擇以後 , 我們找出哪個 subproblem 可 以被拿來應用 , 及剩下的問題 ( 沒有對應到 subp roblem 的 ) 怎麼解決
4.
證明大問題的最佳解中可以直接應用 ( 剪下貼上 )
子問題的最佳解 .
Optimal structure 越簡單越好
=?
=?
� � =?
這一段砍下來就不再砍
成更小的了 ( 拿去賣 ) 這一段是 subprogram, 找遞迴朋友去 解
versus
Optimal structure 越簡單越好
�
1�
�+ 1… �
�
�
�+1�
� +2… �
�1 ≤
�
1 ≤
�< �
在 k 切一刀 假設把問題定義成就好 ( 少一個變數 )
此為一個子問題 此不為一個子問題 !
除非 k 一直都是 j-1, 否則…
Optimal substructure 的變化
1. 原始問題的最佳解用了多少個子問題
2. 大問題有多少選擇 ( 選擇用不同的子問題們來 獲得最佳解 )
大略來說 , 以上兩者決定 dynamic programming a lgorithm 的執行時間 .
( 之前說的 Subproblem graphs 是另外一種算法 )
多少個子問題 有多少選擇 執行時間
鐵條資源回收 n
連串矩陣相乘 n-1
多少個子問題 有多少選擇 執行時間
鐵條資源回收 n
連串矩陣相乘 n-1