• 沒有找到結果。

Programming I Dynamic

N/A
N/A
Protected

Academic year: 2022

Share "Programming I Dynamic"

Copied!
40
0
0

加載中.... (立即查看全文)

全文

(1)

Michael Tsai 2012/10/4

(2)

台大資訊鐵條回收公司

長度 1 2 3 4 5 6 7 8 9 10

價錢 1 5 8 9 10 17 17 20 24 30

 回收鐵條, 依長度算錢.

 假設你有一條很長的鐵條, 長度為n (n為正整數)

 可以把長鐵條砍成長度為整數的短鐵條

 請問如何砍才能夠用這條鐵條換到最多錢?

價目表

(3)

長度為4的鐵條

長度 1 2 3 4 5 6 7 8 9 10

價錢 1 5 8 9 10 17 17 20 24 30 價目表

9 1 8

5 5 1 1 1 1

1 1 5 1 5 1 5 1 1

8 1

(4)

長度為n的鐵條

 長度為n的鐵條, 共有幾種要檢查的?

 每一整數的地方都可以選擇要切, 或不切

 共有n-1個”缺口”

 因此需要檢查2𝑛−1種組合

 Θ(2𝑛−1) 口吐白沫…

(5)

長度為n的鐵條

 讓情況變少種一點

 如果我們規定鐵條只能越砍越大或一樣, 則需要 檢查的不同方式可用partition function來表示

 大約為𝑒𝜋 2𝑛3

4𝑛 3

 仍然為指數(比任何n的多項式都長得快)

(6)

定義一些符號

 𝑝𝑖: 長度為i的鐵條賣價(不再繼續砍)

 𝑟𝑛: 長度為n的鐵條的最高賣價(最佳化砍法)

 如果長度為n的鐵條最佳化砍法把鐵條砍成k段

 𝑛 = 𝑖1 + 𝑖2 + ⋯ + 𝑖𝑘

 𝑟𝑛 = 𝑝𝑖1 + 𝑝𝑖2 + ⋯ + 𝑝𝑖𝑘

(7)

類divide-and-conquer思維

 “我請我的遞迴朋友們來解大小較小但同樣的問 題”

 “假設我知道比較小的問題答案, 如何得出這個 問題的答案?”

𝑟 𝑛 = max⁡(𝑝 𝑛 , 𝑟 1 + 𝑟 𝑛−1 , 𝑟 2 + 𝑟 𝑛−2 , … , 𝑟 𝑛−1 + 𝑟 1 )

不砍刀 這一刀砍在左邊數過來第i個

𝑟𝑖=? 𝑟𝑛−𝑖=?

最後再看哪個砍法為可得到最大值即為解.

(8)

Optimal Substructure

 Optimal solutions to a problem incorporate

optimal solutions to related subproblems, which we may solve independently.

𝑟 𝑛 = max⁡(𝑝 𝑛 , 𝑟 1 + 𝑟 𝑛−1 , 𝑟 2 + 𝑟 𝑛−2 , … , 𝑟 𝑛−1 + 𝑟 1 )

𝑟𝑖=? 𝑟𝑛−𝑖=?

(9)

稍微調整一下

 把subproblem數目變少一點

𝑟 𝑛 = max

1≤𝑖≤𝑛 ⁡(𝑝 𝑖 + 𝑟 𝑛−𝑖 )

𝑝𝑖 𝑟𝑖=?

這一段砍下來就不再砍

成更小的了(拿去賣) 這一段是subprogram, 找遞迴朋友去解

(10)

Cut-Rod v0.1 alpha

Cut_Rod(p,n) if n==0

return 0 q=-∞

for i=1 to n

q=max(q, p[i]+Cut_Rod(p,n-i)) return q

猜猜看, 她會喜歡嗎?

n每增加1, 時間大約x2

(11)

Recursion tree

4

3

2 1 0

1 0 0

0

2 1 0

1 0 0

0

同樣的事情做那麼多遍…浪費時間!

(12)

遞迴式又來拉~

 𝑇 0 = 1

 𝑇 𝑛 = 1 + 𝑛−1𝑗=0 𝑇(𝑗)

 結果:

 T 𝑛 = 2𝑛 (如我們所料)

 <Homework when you have time> :P

 Exercise 15.1-1

(13)

假如我們有點記性的話…

空間換取時間

做過的事情就不要再做

“記得結果”就好: 填表與查表

Dynamic programming: 這裡的 programming指填表, 不是寫程式

所有不同的subprogram數目是 polynomial, 及

解掉subprogram的時間也是 polynomial,

dynamic programming方法可以在 polynomial time內完成

(14)

Dynamic programming的做法

 Top-down with memoization

還是用遞迴的方式來做

但是每次做之前就先檢查是不是做過一樣的

如果沒做過就遞迴下去, 但是要記錄結果

如果做過就用查表取得之前的結果

 Bottom-up method

把所有的subprogram從小排到大

然後從小排到大來解

解一個subproblem時候, 所有它所需要的 subsubproblem都已經被解完了

 請問哪一個快?

 課本p.365有答案.

(15)

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 𝑟 𝑛 ≥ 0

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

p: 價目表 n: 鐵條長度

p: 價目表 n: 鐵條長度 r: 存最佳解的陣列

(16)

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

(17)

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> directed edge

Top-down method: Depth First Search

(18)

Subproblem graphs

 Subproblem graph的大小讓我們可以估計 dynamic programming演算法的執行時間

 大小?

 𝐺 = 𝑉, 𝐸 . 我們指 𝐸 和 𝑉 .

 𝐸 =有幾個要解的subproblem (因為有記結果, 所以一個subproblem只要做一次)

 |𝑉|=每個subproblem需要幾個比它小的 subproblem的結果

 大致的估計: 和 𝐸 和 𝑉 成線性

(19)

最後的小問題

 剛剛的程式只把可以拿多少錢算出來

 沒有真的印出要怎麼切

 如何解決?

 用另外一個陣列(大小Θ(𝑛))紀錄optimal solution 應該切的大小.

 最後依序印出結果即可.

 課本p. 369有解答.

(20)

連串矩陣相乘問題

Matrix multiplication is associative.

(( A1𝐴2 𝐴3)𝐴4)

( A1 𝐴2𝐴3 )𝐴4

A1𝐴2 𝐴3𝐴4

𝐴1( 𝐴2𝐴3 𝐴4)

𝐴1 𝐴2 𝐴3𝐴4

以上算出來答案都一樣

𝐴1 𝐴2 𝐴3 𝐴4 …… 𝐴𝑛

題目: 求𝐴1𝐴2 … 𝐴𝑛矩陣相乘之解.

𝐴1.cols=𝐴2.rows

𝐴1and 𝐴2are compatible.

(21)

連串矩陣相乘問題

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次乘法的時間

(22)

看一個例子

 𝐴1𝐴2 𝐴3 花費之乘法數目=10 × 100 × 5 + 10 × 5 × 50 = 7500

 𝐴1 𝐴2𝐴3 花費之乘法數目=100 × 5 × 50 + 10 × 100 × 50 = 75000

 差十倍!!

10

100 100 5

5

50

(23)

連串矩陣相乘問題-正式版

 給一連串的矩陣 𝐴1, 𝐴2, … , 𝐴𝑛 , 其中矩陣𝐴𝑖的大 小為𝑝𝑖−1 × 𝑝𝑖 (𝑖 = 1, 2, … , 𝑛), 找出一種乘法可 以使計算時的乘法數目最少

 沒有真的要算結果, 而只是找出能最快算出結果 的方法.

 因為算”怎麼算比較快”多花的時間, 比”用爛方 法直接算”多花的時間少很多

(24)

暴力法有多暴力

 全部到底有幾種算法呢?

 用遞迴定義:

 (n)之解為Catalan numbers, Ω 4𝑛

𝑛32 , or is also Ω 2𝑛

𝑃 𝑛 =

1

𝑃 𝑘 𝑃(𝑛 − 𝑘)

𝑛−1 𝑘=1

if 𝑛 = 1, if 𝑛 ≥ 2.

假設先這樣分: 𝐴1𝐴2 … 𝐴𝑘 𝐴𝑘+1𝐴𝑘+2 … 𝐴𝑛

(25)

所以不耍暴力了.

 使用dynamic programming

 正規步驟:

1. 找出最佳解的”結構”

2. 使用遞迴來定義最佳解的花費

3. 計算最佳解的花費

4. 使用已經計算的資訊來構築最佳解

(26)

找出最佳解的”結構”

總花費=𝐴𝑖. . 𝐴𝑘的花費+𝐴𝑘+1. . 𝐴𝑗的花費+把𝐴𝑖. . 𝐴𝑘和𝐴𝑘+1. . 𝐴𝑗 乘起來的花費

最佳解的結構: 假設有𝐴𝑖. . 𝐴𝑗的最佳解, 此一方法為在k切一刀.

則在此𝐴𝑖. . 𝐴𝑗最佳解中, 𝐴𝑖. . 𝐴𝑘的相乘方法一定是𝐴𝑖. . 𝐴𝑘的最 佳相乘方法

假設𝐴𝑖. . 𝐴𝑘不是最佳解, 則我們可以在𝐴𝑖. . 𝐴𝑗中把𝐴𝑖. . 𝐴𝑘換成 更好的方法, 則可以找到一個更好的𝐴𝑖. . 𝐴𝑗的相乘方法矛盾.

子問題的最佳解可以導出大問題的最佳解!

最後結論: 分成兩個子問題, 並嘗試所有可以切分的地方(k值)

𝐴𝑖𝐴𝑖+1… 𝐴𝑘 𝐴𝑘+1𝐴𝑘+2… 𝐴𝑗

𝑖 ≤ 𝑗

𝑖 ≤ 𝑘 < 𝑗 在k切一刀

(27)

使用遞迴來定義最佳解的花費

 遞迴定義:使用子問題最佳解的cost來定義大問 題最佳解的cost

 定義: 𝑚[𝑖, 𝑗]為𝐴𝑖. . 𝐴𝑗所需花的最少乘法數

 𝐴𝑖..𝑘𝐴𝑘+1..𝑗所花乘法數=𝑝𝑖−1𝑝𝑘𝑝𝑗

𝐴𝑖..𝑘 𝐴𝑘+1..𝑗

𝐴𝑖.rows=𝑝𝑖−1

𝐴𝑘.cols=𝑝𝑘

𝐴𝑘+1.rows=𝑝𝑘

𝐴𝑗.cols=𝑝𝑗

(28)

使用遞迴來定義最佳解的花費

 𝑚 𝑖, 𝑗 = 𝑚 𝑖, 𝑘 + 𝑚 𝑘 + 1, 𝑗 + 𝑝𝑖−1𝑝𝑘𝑝𝑗

 但是我們不知道最佳解中的k的值

 因此我們必須找所有𝑘 = 𝑖, 𝑖 + 1, … , 𝑗 − 1

 最後版本:

𝑚 𝑖, 𝑗 = 0

𝑖≤𝑘<𝑗

min {𝑚 𝑖, 𝑘 + 𝑚 𝑘 + 1, 𝑗 + 𝑝

𝑖−1

𝑝

𝑘

𝑝

𝑗

} if 𝑖 = 𝑗,

if 𝑖 < 𝑗.

(29)

計算最佳解的花費

 純recursive解法: exponential time

 使用前面教的Bottom-up填表方法: 每個不同的 subprogram僅需解1次

 有幾個不同的問題?

 1 ≤ 𝑖 ≤ 𝑗 ≤ 𝑛, 幾個i和j的組合?

 答案: 𝑛

2 + n = Θ 𝑛2

𝑖 ≠ 𝑗 𝑖 = 𝑗

(30)

計算最佳解的花費

 如何決定填表的順序呢? (這次有i,j兩個變數)

𝑚 𝑖, 𝑗 = 0

𝑖≤𝑘<𝑗min {𝑚 𝑖, 𝑘 + 𝑚 𝑘 + 1, 𝑗 + 𝑝𝑖−1𝑝𝑘𝑝𝑗} if 𝑖 = 𝑗, if 𝑖 < 𝑗.

𝑘 − 𝑖 + 1個矩陣相乘 𝑗 − 𝑘個矩陣相乘 都小於𝑗 − 𝑖 + 1個

我們可以把j-i+1(也就是要相乘的matrix個數) 當作problem size的定義

(31)

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]+pi−1𝑝𝑘𝑝𝑗 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)

(32)

計算最佳解的花費

 用一個例子來trace code比較快

Matrix 𝑨𝟏 𝑨𝟐 𝑨𝟑 𝑨𝟒 𝑨𝟓 𝑨𝟔

Dimension 30 x 35 35 x 15 15 x 5 5 x 10 10 x 20 20 x 25

(33)

使用已經計算的資訊來構築最佳 解

 前面只印出了花費, 不是真正的解

 怎麼乘才是最後的解

 使用s陣列的資訊

(34)

使用已經計算的資訊來構築最佳 解

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 “)”

(35)

看了兩個例子以後…

 問: 一個問題要有什麼要件才能使用dynamic programming?

 答:

1. Optimal substructure

2. Overlapping Subproblems

(36)

什麼是Optimal substructure?

 Definition: A problem exhibits

optimal substructure if an

optimal solution to the problem contains within it optimal

solutions to subproblems.

 怎麼尋找optimal substructure呢?

(37)

怎麼尋找optimal substructure呢?

1. 要得到問題的解答有許多選擇(砍在哪邊, 切在哪 邊), 而做這個選擇之後, 我們有一些subproblem要 解決.

2. 我們假設對於一個問題, 我們可以找到那個選擇

3. 知道這個選擇以後, 我們找出哪個subproblem可以 被拿來應用, 及剩下的問題(沒有對應到subproblem 的)怎麼解決

4. 證明大問題的最佳解中可以直接應用(剪下貼上)子 問題的最佳解.

(38)

Optimal substructure越簡單越好

𝑟𝑖=? 𝑟𝑛−𝑖=?

𝑝𝑖 𝑟𝑖=?

這一段砍下來就不再砍

成更小的了(拿去賣) 這一段是subproblem, 找遞迴朋友去解 versus

(39)

Optimal substructure越簡單越好

𝐴1𝐴𝑖+1… 𝐴𝑘 𝐴𝑘+1𝐴𝑘+2 … 𝐴𝑗

1 ≤ 𝑗

1 ≤ 𝑘 < 𝑗

在k切一刀 假設把問題定義成𝐴1 … 𝐴𝑗就好 (少一個變數)

此為一個子問題 此不為一個子問題!

除非k一直都是j-1, 否則…

(40)

Optimal substructure的變化

1. 原始問題的最佳解用了多少個子問題

2. 大問題有多少選擇(選擇用不同的子問題們來 獲得最佳解)

大略來說, 以上兩者決定dynamic programming algorithm的執行時間.

(之前說的Subproblem graphs是另外一種算法)

多少個子問題 有多少選擇 執行時間

鐵條資源回收 Θ(𝑛) n 𝑂 𝑛2

連串矩陣相乘 Θ(𝑛2) n-1 𝑂 𝑛3

參考文獻

相關文件

• 我們通常用 nD/mD 來表示一個狀態 O(N^n) ,轉移 O(N^m) 的 dp 演算法. • 在做每題

• 也就是 ”我的dp是n^3”這句話本身不夠表示你的dp演算法,必須 要說“我的dp是個狀態n^2,轉移n”才夠精確. •

[r]

✓ Express the solution of the original problem in terms of optimal solutions for subproblems. Construct an optimal solution from

[r]

✓ Express the solution of the original problem in terms of optimal solutions for subproblems.. Construct an optimal solution from

• 有一個可以耐重 W 的背包,及 N 種物品,每種物品有各自的重量 w[i] 和價值 v[i] ,且數量為 k[i] 個,求在不超過重量限制的情 況下往背包塞盡量多的東西,總價值最大為多少?.

依賴背包問題 and