一、動態規劃三板斧
- 狀態轉移公式
- 循環 或 遞歸
- 性能優化
二、WHY
1、狀態轉移公式
動態規劃與分治不一樣,分治的問題是相互獨立的,而動態規劃的各個狀態是有關聯關係的。比如揹包問題,你選擇了 i 物品之後,揹包的剩餘容量要發生變化吧,對裝別的物品就有影響了。
狀態轉移公式就是刻畫這種關聯的,一旦知道了這種關係,就可以道生一,一生二,二生三,三生萬物了。
怎麼生萬物呢?
靠循環。
2、循環&遞歸
爲了窮盡所有可能。
值得注意的是:循環一般是從前往後思考,而遞歸往往是從後往前考慮。
3、性能優化
正是要窮盡所有可能,動態規劃的時間複雜度通常是指數級的,性能很差。動態規劃還有維度爆炸的問題,就是當考慮的維度過多時,窮盡不過來了。因此一定要做性能優化,最經典的方式就是以空間換時間。
總結來說:
動態規劃,就是用狀態轉移公式建立關係,用循環窮盡所有可能,最後撿出符合的答案。
三、HOW
如何運用這三板斧?
1、找到狀態轉移公式
① 藉助幾何圖形看關係
比如揹包問題中,列出表格;找零問題中,建立樹形圖;楊輝三角問題,畫出楊輝三角。
不要小看列表格的過程。
不要小看列表格的過程。
不要小看列表格的過程。
我一開始覺得看看別人列的表格就行了,後來才發現列表格的過程就是理解動態規劃的開始。
不要動眼不動手。
② 確定問題維度
一維問題,一個參數就能表示,比如爬樓問題狀態用 f ( n )就能表示。二維問題,比如楊輝三角問題,用 f ( x, y )表示一個節點狀態。
③ 確定邊界條件
邊界條件是你遞歸的出口,或者循環的起點。下面幾種是常見的邊界調節-
x === 1 return ...
y <= 0 return ...
④ 列出狀態轉移公式和邊界條件
2、循環/遞歸
要遞歸的內容,和遞歸的出口,上一步已經定好了。這裏直接拿來用就行了。
3、性能優化
遞歸時,很容易導致重複計算。這時用空間換時間,將計算過的狀態儲存起來,然後也作爲遞歸的出口,碰到計算過的數據,直接取值即可。
四、如何入門動態規劃
思想是無形的,動態規劃尤其細膩、微妙,要用有形來攻無形。可以聯繫下面幾道經典題目,能幫助你學習無形的思想。
由淺到深:
- 斐波那契數列
- 爬樓梯問題
- 機器人走方格問題
- 楊輝三角(變形)問題
- 01揹包問題
- 找硬幣問題
等你深入理解這些問題之後,會發現它們有着很多相似處,有的更是相互的變形。然後你對動態規劃就會有更立體的認識,而且會體會到其中的樂趣。