咱們知道的思想就是將大問題拆分紅小問題進行攻破;
好比鋼條切割問題:
給定一段長度爲n的鋼條和以下的價格表,求切割鋼條方案,使得收益最大 算法
咱們很容易想到經過遞歸進行求解:
假設price(x)表明長度x的鋼材的最大收益,咱們很容易將問題進行遞歸分解:
函數
price(n) = max(pi, price(1)+price(n-1), price(2)+price(n-2),....,price(n-1)+price(1) );
複製代碼
好比,咱們求解一根長度爲4的鋼材的切割方式:
就是求取各類組合的最大利益
post
price(4) = max(p4, price(1) + price(3), price(2) + price(2), price(3) + price(1));
複製代碼
這種自頂向下分解遞歸的方式確定是能夠解決這個鋼條切割的問題的,可是有沒有缺陷?優化
有的,還不小,就是效率問題。
隨着x的增大,遞歸的效率會愈來愈低,運行速度會很慢,由於什麼?
spa
由於它在反覆求解相同的問題
在price(3)時,其已經計算過3的最優解了,且二、1的確定也有了;
做爲人類,咱們天然而然就會將這個結果記住,並用於下次計算;
可是遞歸不會,在price(4)的時候,其仍然還會計算price(3),price(2),price(1),不論是不是上次遞歸已經計算過了。
複製代碼
那麼解決這個問題的很簡單的辦法是什麼?3d
沒錯,就是
將先前解決的子問題,進行存儲,以減小重複計算! 這就是code
好了,貌似咱們討論到如今都是說的遞歸問題,其實呢,到目前爲止,咱們已經講完了動態規劃的本質:cdn
1.動態規劃是經過組合子問題的解來解決原問題
2.動態規劃應用於子問題重疊的狀況,即不一樣的子問題具備公共的子子問題
3.動態規劃算法對每一個子子問題只求解一次
4.動態規劃一般用來求解最優化問題
複製代碼
動態規劃算法:blog
1.刻畫一個最優解的結構特徵
2.遞歸的定義最優解的值
3.計算最優解的值,一般自底向上
4.利用計算出的信息構造一個最優解
複製代碼
好了,讓咱們用動態規劃解一下鋼條切割問題:遞歸
1.刻畫一個最優解的結構特徵
遞歸法中已經刻畫的很清楚了
2.遞歸的定義最優解的值
公式也在上面寫過了
3.計算最優解的值,一般自底向上
經過帶備忘的自頂向下遞歸法,咱們成功的比較高效的解決了鋼鐵切割的問題,這也是動態規劃的一種方式,有沒有其餘方式?
有的,對應於自頂而下,咱們採用自底而上的方式,將子問題按照從小到大的順序進行求解,固然仍是得有備忘機制。
大部分狀況下,自頂而下和自底而上的效率是近似的;可是呢,在某些特殊狀況,自頂向下方法並未真正的遞歸考察全部可能的子問題;並且自底向上也沒有頻繁的遞歸函數的開銷;
因此,通常動態規劃都是採用自底向上的方法,將複雜的問題,變成了簡單的多項式相加。
4.利用計算出的信息構造一個最優解
這條就更簡單了,既然你算法都寫出來了,在算法的途中,加上最優解的存儲及輸出就能夠了,
好比動態規劃鋼鐵切割問題,在算法最初,咱們關心的是price(n),計算出最佳的收益;
最後咱們只要在編寫出的算法中,加上輸出鋼鐵的分割就能夠了。
複製代碼
鋼鐵切割問題自己就是個典型的動態規劃,除了這個例子,還有:
最長公共子序列
最優二叉搜索樹
矩陣鏈乘法
....
複製代碼
不論是什麼問題,本質上咱們都是經過層層分解子問題,並進行組合;
若是這個問題,知足上述特性,那麼動態規劃就是這些問題可能的解決方法之一。
某些問題是否適用於動態規劃算法,你能夠從以下角度:
1.是否具備最優子結構性質
若是一個問題的最優解,包含其子問題的最優解
2.具備重疊子問題性質
問題的遞歸算法會反覆求解相同的子問題
複製代碼
算法的精髓在於,其沒有最好,只有最合適
其餘相關章節
複製代碼
算法相關文章之一:《簡單說說二叉搜索樹》
算法相關文章之二:《B樹,一點都不神祕》
算法相關文章之三:《B樹很簡單,插入so easy》
算法相關文章之四:《什麼是動態規劃》
算法相關文章之五:《LCS,給你一個不同的模糊匹配》