動態規劃和貪心算法

動態規劃和貪心算法都是用來求最優化問題,且二者都必須具有最有子結構。貪心算法可以解決的問題,動態規劃都能解決,可以說,貪心算法是動態規劃的一個特例。

貪心算法和動態規劃最大的不同在於,它並不是首先尋找子問題的最優解,然後在其中進行選擇,而是首先做一次貪心選擇——在當時(局部)看來最有選擇——然後求解選出的子問題,從而不必費心求解所有可能相關的子問題。



動態規劃

動態規劃(dynamic programming)與分治法相似,都是通過組合子問題的解來求解原問題。分治法將問題劃分爲互不相交的子問題,遞歸求解子問題,再將它們的解組合起來,求出原問題的解。與之相反,動態規劃應用於子問題重疊的情況,即不同的子問題具有公共的子子問題(子問題的求解釋遞歸進行的,將其劃分爲更小的子子問題)。這種情況下,動態規劃對公共子子問題只求一次解,而分治法會反覆求解公共子子問題。
我們通常按如下四個步驟來設計一個動態規劃算法:
  1. 刻畫一個最優解的結構特徵(如果一個問題的最優解包含其子問題的最優解,就稱此問題具有最有子結構性質)。
  2. 遞歸的定義最優解的值。
  3. 計算最優解的值,通常採用自底向上的方法。
  4. 利用計算出的信息構造一個最優解。
eg:最長公共子序列(LCS)問題。



貪心算法

求解最優化問題的算法通常需要經過一系列的步驟,在每個步驟都面臨多種選擇。對於許多最優化問題,使用動態規劃算法求最優解有些殺雞用牛刀了,可以使用更簡單更優化的算法,即貪心算法(greedy algorithm)。它在每一步都做出當時看起來最佳的選擇。也就是說,它總是做出局部最優的選擇,寄希望這樣的選擇能導致全局最優解。貪心算法並不保證得到最優解,但對很多問題確實可以求得最優解。
可以按如下步驟 設計貪心算法:
  1. 將最優化問題轉化爲這樣的形式:對其作出一次選擇後,只剩下一個子問題需要求解。
  2. 證明作出貪心選擇後,原問題總是存在最優解,即貪心選擇總是安全的。
  3. 證明作出貪心選擇後,剩餘的子問題滿足性質:其最優解與貪心選擇組合即可得到原問題的最優解,這樣就得到了最優子結構。
貪心選擇性質(greedy-choice property):我們可以通過作出局部最優(貪心)選擇來構造全局最優解。換句話說,當進行選擇時,我們直接作出在當前問題中看來最優的選擇,而不必考慮子問題的解。
這也是貪心算法與動態規劃的不同之處。在動態規劃方法中,每個步驟都要進行一次選擇,但選擇通常依賴於子問題的解。因此,我們通常以一種自底向上的方式求解動態規劃問題,先求解嬌小的子問題,然後是交大的子問題(我們也可以自頂向下求解,但需要備忘機制。當然,即使算法是自頂向下進行計算,我們仍然需要先求解子問題再進行選擇)。在貪心算法中,我們總是做出當時看來最佳的選擇,然後求解剩下的唯一子問題。貪心算法進行選擇時可能依賴於之前做出的選擇,但不依賴於任何將來的選擇或是子問題的解。因此,與動態規劃先求解子問題才能進行第一次選擇不用,貪心算法在進行第一次選擇之前不求解任何子問題。一個動態規劃算法是自底向上進行計算的,而一個貪心算法通常是自頂向下的,進行一次又一次選擇,將給定問題實例變得更小。
eg:赫夫曼編碼、最小生成樹算法(Kruskal算法和Prim算法)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章