Chapter Chapter Chapter
Chapter 4 44 4 動態規劃 動態規劃 動態規劃( 動態規劃 ( ( (Dynamic Dynamic Dynamic Dynamic Programming Programming Programming Programming) ) ) )
●Section 1 概論(Introduction)
動態規劃與分而治之的基本想法是相近的,都是把問題不斷分割成比較小的子問題,直 到我們可以直接解決,之後再由子問題的結果推出大問題的答案。但在遞迴的過程中,經常 會發生同樣一個子問題被處理了好幾次的狀況;如:為了得到問題 A 的答案會用到問題 B 與 C 的結果、得到問題 B 的答案也需要用到問題 C 的結果,此時 A 與 B 有相同的子問題 C,在 遞迴的過程中問題 C 就會被重複做了兩次,許多的這種狀況發生便大幅浪費了時間。動態規 劃的精髓便是把處理過的問題答案儲存在一張表中,在第二次執行的時候直接呼叫表中的 值,以避免這種浪費時間的情況發生。
§1-1 動態規劃的特性
通常會使用動態規劃來解決的問題分成兩種:最佳化問題與計數問題,而能套用動態規 劃方法的問題通常要具備以下幾個條件:
1. 最佳子結構:在把問題分割成比較小的子問題時,先假設我們能得到比較小的問題的答 案,我們要能夠藉由某種過程從這些答案推出母問題的答案。有時問題的子問題會互相影響,
或著母問題最佳化時子問題不一定達到最佳,需要特別注意每個推論的正確性。
2. 重疊的子問題:在有重疊的子問題,即會重複利用相同的子問題的結果時,使用動態規劃 才有節省時間的意義,否則只是徒然浪費空間儲存不需要再次使用的結果而已。
3. 無後效性:解決動態規劃問題的過程可以分為幾個階段,使得每個階段所做的決策只與之 前階段的結果有關,而與尚未出現的狀態無關。也就是說將每個狀態與其決策時相關的狀態 以有向邊相連後,所產生的圖是一個有向無環圖(DAG)。
§1-2 名詞定義
狀態:描述一個我們將要去解決的子問題之性質。
階段:一些性質相近,可以同時處理的狀態集合。
決策:每個階段中做出的一些選擇性的行動,也就是我們的程式所需要做出的選擇。
狀態轉移方程:如何藉著其他狀態的答案算出某一狀態的答案,通常以遞迴式表示。
對於一個動態規劃算法,通常其時間複雜度為狀態數*狀態轉移花費,而其空間複雜度至 少為在某時刻所有已解決且之後可能被使用到的狀態數。
§1-3 動態規劃問題的解決方法
(1) 設計狀態,即使用幾個特性去描述一個子問題,使可能出現的狀態種數不會太多(別忘了 動態規劃的時間複雜度直接取決於狀態數),且狀態轉移過程中所有可能被使用到的子問 題都能被這幾個特性去具體精確的描述。這也是解決動態規劃問題過程中最重要的一個 步驟。
(2) 推導狀態轉移方程,即如何利用其他狀態的答案推出這個狀態的方法。值得注意的是狀 態轉移的過程必須要能建立一個決策順序,也就是不能有 A 狀態的答案依賴於 B 狀態,
而 B 狀態亦直接或間接的依賴於 A 狀態的狀況發生。
(3) 分析算法的正確性及時空花費,若時空花費無法滿足題目需求,則必須再想方法去優化 你的算法的過程。
§1-4 動態規劃的實踐方式
分為 top-down 與 bottom-up 兩種,其中 bottom-up 即依照一定的決策順序枚舉每個 狀態,對其依序套用狀態轉移方程求出結果。而 top-down 的方法即在搜索時提到過的 memoization,對遞迴過程中每個狀態的答案做紀錄,並在再次呼叫時直接回傳答案,通常 於其狀態的決策順序難以枚舉或狀態並不會完整擴展時較為適合。
§1-5 回溯(backtracking)
對於某些問題,我們不止需要輸出多次決策後的最佳花費,還需要輸出最佳決策的過程。
此時對於每個狀態皆紀錄其完整決策過程是明顯不實際的。通常解決方法為在動態規劃的過 程中,對每個狀態紀錄其最後一步決策,並在需輸出最後的決策過程時,從最後的狀態開始 回溯,每次讀取其最後一步決策並回到決策前的狀態,直到回到初始狀態即可獲得最佳決策 的過程。
●Section 2 題目與經典方法介紹
對動態規劃方法的熟悉需要對大量題目的練習及經典方法的認識,但是更重要的是在經 典題目的思考過程中感受動態規劃的想法,培養對題目及如何設計狀態的感覺,以下為一些 例題:
題一《鉛塊鈾塊 Critical Mass》(UVA 580)
一個字串由許多 U 和 L 構成,給定字串長度,問有幾種有超過兩個 U 連在一起的字串?
遞迴式:______________________________________________________________________________
題二《最大 0 組成正方形》(TIOJ1097, 營地)
在一個零一矩陣中,找一個最大的正方形,裡面全部都是 0。
遞迴式:______________________________________________________________________________
題三《n 箱 m 球》(TIOJ1291)
n個相同的箱子要放入m個不同的球,問有幾種放法。
遞迴式:______________________________________________________________________________
題四《找錢問題》(UVA674, Coin Change)
給定一些幣值,問要恰好湊出m元,至少要用多少個硬幣?
遞迴式:______________________________________________________________________________
如果問有幾種湊出 m 元的方法數呢?__________________________________________________
題五《背包問題》(TIOJ1387, Striker 的秘密)
一個背包能裝載重量T,有n種物品重量分為w1,w2,…wn,價值m1,m2,…mn,分別有c1,c2,…cn 個,至多能裝入總價值多少的東西?
遞迴式:______________________________________________________________________________
如果每件物品可以放無限個呢?_______________________________________________________
如果物品經過分組,每組最多選一件呢?______________________________________________
觀察遞迴式,可否利用先前教過的資料結構來進行加速?_______________________________
題六《矩陣相乘》(UVA442, Matrix Chain Multiplication)
有n個矩陣要相乘,問在不同的相乘順序中,至少要做多少數之間的乘法運算?
遞迴式:______________________________________________________________________________
題七《最長共同子序列》(UVA10405,Longest Common Subsequence)
給定兩個字串,請在分別刪除兩個字串中的某些字母,使得剩下的子字串完全相同,且子 字串長度最長。例如 algorithm 和 alcoholism 的 LCS 是 aloim。
遞迴式:______________________________________________________________________________
如果限制兩字串之配對數(即(i,j)之數量使ai=bj)不多,但字串長度可能很長,要怎麼做?
題八《編輯距離》(TIOJ1385, 芳佳的打工)
給定兩個字串,每次可以從一個字串中插入、刪除或取代一個字元,問至少要操作多少次 才能將其變成另一個字串。
遞迴式:______________________________________________________________________________
題九《最長遞增子序列》(TIOJ1175, Longest Increasing Subsequence)
給定一個由n個數字所構成的序列,定義它的一個遞增子序列是它的一個子序列,且滿足 該子序列是遞增的(後面的數≥前面的數)。請求出它的遞增子序列最長能到多長?
遞迴式:______________________________________________________________________________
你的複雜度為多少?有辦法O(nlgn)嗎?__________________________________________
題十《燈泡問題》(95 年建中校內賽考題)(TIOJ1007)
假設一個燈泡最多可以持續點亮 n單位的時間而不燒斷,而總時間是 m單位時間。
請寫一個程式,給定n和m的值,算出有幾種不同的明暗排列方式,每一種排列方式之中 都不會出現亮超過連續 n單位時間的區段。
遞迴式:______________________________________________________________________________
題十一《A game》(96 年建中校內賽考題)(TIOJ1029)
「A 遊戲」是個由兩個人玩的遊戲:有一串由N個正整數所組成的數列,兩個玩者輪流拿 走一個最左邊或最右邊的數,直到最後所有的數都取完之後,兩個玩者分別把自己所取到 數加總,分數較高的人獲勝。假設兩個玩者都是最佳玩家,兩者都不會犯錯,會就目前狀 況盡自己的力取得盡量多的分數──試求兩個玩家所能得到的最高分數各為多少?
遞迴式:______________________________________________________________________________
題十二《最大連續元素和》
給定一個序列,問連續元素的和最大可為多少?
遞迴式:______________________________________________________________________________
同樣的方法可否推廣到超過一維的狀況?(即最大子矩陣和之類的)_______________________
題十三《糊塗情報員》(95 年全國賽)(TIOJ1145)
給定一個算式,要求求出加了若干括號後的最大值。
遞迴式:_______________________________________________________________________________
題十四《水球硬度測試》(UVA 10934)
有一棟n層樓的高樓(n≤264),與k顆水球(k≤100)。你想要測試水球最高從幾層樓掉下 來還不會破。如果測試後水球沒破,可以繼續使用;反之若破了,就無法再使用。
試問:至少要測試幾次,才可以確知水球最高從幾層樓掉下來還不會破?(若要超過63次,
則輸出 More than 63 trials needed.)
遞迴式:_______________________________________________________________________________
題十五《製造回文 Palindrome》(UVA 10944)
現在給你一個字串,請問最少插入幾個字可以使其變成一個回文
遞迴式:_____________________________________________________________________________
題十六《三元樹》(09TOI 一階第二次模考)
給定n,m (n≤10000),求n個節點的三元樹種類數除m的餘數?
遞迴式:_____________________________________________________________________________
題十七《保加利亞的多邊形》(TIOJ1263)
給定n(n<50)個不共線的點,請問這些點可形成之最小凸 k(k<11)邊形面積為何?
遞迴式:_____________________________________________________________________________
題十八《赫密士神 Hermes》( 2004IOI )
Hermes 要依序送信給n(≤20000)個神,他可以送信給一個神的條件是他們在同一行或同一 列上,給定 Hermes 的起點及n個神各自的位置(|Xi|,|Yi| ≤1000),請問 Hermes 至少要移動 多遠才能送完所有信?
遞迴式:_____________________________________________________________________________
題十九《菲迪亞斯神 Phidias》( 2004IOI )
Phidias 想把尺寸w*h (w,h≤600)的大理石板切成許多塊,其中每一步切割都是從橫向或直 向貫穿切成兩塊。而最後只有n (n≤200)種尺寸的大理石板可供使用,尺寸不對的只好丟 棄,求丟棄的最小面積。
遞迴式:_____________________________________________________________________________
題二十《山景 skyline》( TIOJ1471 )
一座山的山稜線由n段(n≤3000)的45度斜坡構成,每一個片段不是上坡就是下坡。給定n,
請問有多少種山稜線的形狀,使得所有山頂的位置由左而右非遞減呢?
遞迴式:_____________________________________________________________________________
題二一《空罐 cans》( TIOJ1473 )
給定一開始的一個起始存活字串及n個有害字串。每天每個存活的字串會新產生四個字 串,即分別在字串後加上a,b,c,d,而原來的字串則會縮短一個字母(第一個字母消失)。如 果一個字串長度為0,則他會以死法 1 死亡;如果字串中有一個子字串為有害字串,那它 就會以死法 2 死亡,請問p天後分別有多少字串以死法 1,2 死亡?(過程中所有存活字串長 度≤100,n≤100,有害字串長≤15,p≤300)
遞迴式:_____________________________________________________________________________
§2-1 狀態壓縮
在某些時候要記錄的特性不止常數個,例如一個由 1 到 n 中某些元素所成的集合,需要 用 n 個 0 或 1 來表示,此時我們無法直接開一個 n 維的陣列來記錄狀態。解決方法是利用二 進位的方法,將此 n 個 0,1 壓成一個數字,並直接開一個大小為 2n的一維陣列來記錄狀態。
通常我們把類似此種形式的 DP 稱為狀態壓縮。另外在實作此種方法時經常會利用位元運算 來協助與加速。
題一《松鼠吃松果》( UVA10944 )
格子上有n (≤15)個松果。試問從原點出發,最少要走多少距離才能吃到所有松果再走回原
點?
遞迴式:______________________________________________________________________________
題二《鍊金術》( TIOJ1390 )
有n(≤15)個物質,給定任兩個物質融合可得價值及其融合後會剩下哪一個物質,請問最多
可以獲得多少價值?
遞迴式:______________________________________________________________________________
題三《巧拼放置問題》( TIOJ1452 )
要在一個n*m (n ,m≤13)的房間裡用 1*2 的巧拼鋪滿,請問有幾種方法?
遞迴式:______________________________________________________________________________
題四《晶片放置問題》( TIOJ1468 )
要在一個n*m但有k格損壞的晶圓上放置2*3的晶片(n≤500, m≤10),給定損壞的格子,試 問最多可放多少晶片(當然,已損壞的位置不可放置)?
遞迴式:______________________________________________________________________________
§2-2 樹型動態規劃
對於一棵有根樹來說,以某點為根之子樹為以其所有孩子為根之子樹再加上它自己,故 對於以每棵子樹上的性質之計算經常也是可以使用動態規劃方法解決的,泛稱為樹型 DP。
題一《子樹結點求和》
給定一棵n個結點的有根樹,每個結點有重量,請求出以每個結點為根之子樹上所有結點 之重量和。
遞迴式:______________________________________________________________________________
題二《樹論之最遠距點對》( TIOJ1213 )
給你一棵n(n≤100,000)個結點,邊帶權的無向樹,請問最遠的兩個點距離為何?
遞迴式:______________________________________________________________________________
題三《strings》( 11th POI )
給定一個n(n≤10000)個結點的樹狀結構,請問最少要用幾條繩子才能造出這個結構。另外
在使用最少條繩子的狀況下,請求最長的繩子長度至少要多長?
遞迴式:______________________________________________________________________________
題四《一字千金》( TIOJ1528 )
給定一個n (n≤50000)個點m (m≤n+7)條邊的連通圖,每個點有權重,請選出一個點集使其 中各點兩兩不相鄰並使此點集權重和最大。
遞迴式:______________________________________________________________________________
題五《rivers》( 2005IOI )
Byteland 的河流從下游往上游形成了一個n個結點的樹狀結構,其中每個結點上都是一個 城鎮,給定每個城市每年生產的木材量及每條河流的長度。每個城鎮所砍的樹將順流向下 運送。目前在最下游的城鎮已蓋有伐木廠,而希望在k個城市中再多蓋伐木廠使得將所有 木材順流運至伐木廠的花費最小(花費=木材數*運輸距離)?(n≤100,k≤50)
遞迴式:______________________________________________________________________________
題六《收費站問題》( 09TOI 一階第一次模考 )
給一棵n個結點的二元樹,對每個結點i有Si個人要從根節點出發去i旅遊,現在要取k 條邊設收費站,每經過一個收費站每人就要收一元,從根節點出發也要收一元的旅遊費。
這k個收費站會把樹分成k+1個區塊,每個要去區塊i的總收費是Ti。求Ti之中的最大值 最小是多少(n≤200, k≤50, Si≤50)?
遞迴式:______________________________________________________________________________
§2-3 動態規劃優化
一個動態規劃算法的效率通常有兩個要素決定:(1) 所牽涉到的狀態數目 (2) 每次狀態 轉移所需時間。欲在動態規劃的效率上進行優化,通常是利用問題、狀態或轉移方程的特性 來協助,幾種方法如下:
1. 重新設計狀態:有時候其實不需要那麼多的狀態就能解決問題,或著在某些不同的狀態設 計下才能進行其他的優化,這時重新設計狀態就能幫助改進算法之效率。
2. 增加狀態:增加狀態貌似無益於改進算法效率,但其實有時候我們在狀態轉移的過程中也 有重複的計算,則使用類似再 DP 一次的想法或許可以大幅加快轉移速度。
3. 結合資料結構:有時候一些支援各種操作的資料結構可以幫助我們加速轉移的過程,如 deque, heap, BST……等。
4. 使用單調性:使用凸/凹四邊形不等式協助證明決策之單調性,做法較為複雜,有興趣的 人可以參閱算法藝術中的相關章節。
5. 使用稀疏性:在某些動態規劃問題中,只需考慮一小部份的問題的解,則我們可能可以只 計算一小部分狀態而非所有狀態,以達加速效果。.
題一《最佳搜尋二元樹 Optimal Binary Search Tree》(UVA10304)
對於同一組數值資料,所形成的二元搜尋樹可能有很多種。現在給你每個數被查詢的次數,
試找出其中一種二元搜尋樹,使得所有數字被查詢時的總比較次數最少。
遞迴式:_______________________________________________________________________________