動態規劃與搜尋遞推的區別

2021-10-05 01:33:14 字數 2091 閱讀 2494

動態規劃是解決某一類的問題,而不在於糾結遞推還是遞迴,記憶體換時間。

cpu記憶體裡儲存的所有資料構成了當前狀態,cpu只能利用當前狀態計算出下乙個狀態。

下乙個狀態只能由當前狀態計算出來。

斐波那契,每求乙個新數隻需要之前的兩個狀態,只需要依照固定的模式從舊狀態計算出新狀態就行。

不需要考慮是不是需要更多的狀態,也不需要選擇哪些舊狀態來計算新狀態。對於這樣的解法,叫做遞推。

斐波那契例子過於簡單,讓人忽略了階段的概念。階段是指在同一時刻可能會得到的不同狀態的集合。斐波那契中每一步計算得到乙個新數字,所以每乙個階段只有乙個狀態,加入把你放在圍棋棋盤上,每一步只能走一格,每一步都有東南西北四個方向可以走,所以當你同樣走四步可能會處於很多個不同的位置,從頭開始走了幾步就是第幾個階段,走了n步可能處於的位置稱為乙個狀態,走了這n步所有可能到達的位置的集合就是這個階段下所有可能的狀態。

每個階段有很多個狀態

好在有時我們並不需要真的計算所有狀態,比如:從棋盤上的左上角到右下角最短需要幾步。

每個階段確實可以有很多狀態(走n步可以走很多位置),但是同樣的n步中,有哪些位置可以讓我們在n+1步中走的最遠呢?沒錯,正是第n步中走的最遠的位置(?)。下一步最優是從當前最優得到的,所以為了計算最終的最優值,只需要儲存每一步的最優值即可,解決這種性質的問題的演算法叫貪心,如果只看最優狀態之間的計算郭晨是不是很像,所以計算的方法是遞推。

問題劃分為階段和狀態。這樣一來我們一下子就解決了大類問題,乙個階段的最優可以由前乙個階段的最優得到

如果乙個階段的最優無法用前乙個階段的最優得到呢?

什麼你說只需要之前兩個階段就可以得到當前最優?那跟只用之前乙個階段並沒有本質區別。最麻煩的情況在於你需要之前所有的情況才行。

再舉迷宮的例子,在計算從起點到終點的最短路線時,你不能只儲存當前階段的狀態,因為題目要求最短,所以你必須知道之前走過的所有位置。因為即使你當前在的位置不變,之前的路線不同會影響你的之後走的狀態。這時你需要儲存的是之前每個階段所經歷的那個狀態,根據這些資訊才能計算出下乙個狀態。

每個撞他都可以轉移到下乙個階段的多個狀態,解的複雜度就是指數的,之前的路線會影響到下一步的選擇,這個叫做後效性。

剛剛的情況實在太普遍,解決方法實在太暴力,有沒有哪些情況可以避免如此的暴力呢?

契機就在於後效性。

有一類問題,看似需要之前所有的狀態,其實不用。不妨也是拿最長上公升子串行的例子來說明為什麼他不必需要暴力搜尋,進而引出動態規劃的思路。

最長的上公升子串行問題:

輸入: [10,9,2,5,3,7,101,18]

輸出: 4

解釋: 最長的上公升子串行是 [2,3,7,101],它的長度是 4。

從頭到尾依次列舉是否選擇當前的數字,每選定乙個數字就要去看看是不是滿足「上公升」性質,這裡的第i個階段就是去思考是否選擇第i個數,第i個階段有兩個狀態,分別是選和不選。(迷宮是東南西北)。而這裡因為是需要上公升的序列,每次我選擇當前數字的時候,只需要和之前選定的數字比較就行了!這和之前的迷宮問題有本質不同、這就可以縱容我們不需要記錄之前所有的狀態啊!既然我們的選擇已經不受之前狀態的組合的影響了,那時間複雜度自然也不是指數的了啊!雖然我們不在乎某序列之前都是什麼元素,但我們還是需要這個序列的長度的。所以我們只需要記錄以某個元素結尾的lis長度就好!因此第i個階段的最優解只是由前i-1個階段的最優解得到的,然後就得到了dp方程

所以乙個問題是該用遞推、貪心、搜尋還是動態規劃,完全是由這個問題本身階段間狀態的轉移方式決定的!

每個階段只有乙個狀態->遞推;

每個階段的最優狀態都是由上乙個階段的最優狀態得到的->貪心;

每個階段的最優狀態是由之前所有階段的狀態的組合得到的->搜尋;

每個階段的最優狀態可以從之前某個階段的某個或某些狀態直接得到而不管之前這個狀態是如何得到的->動態規劃。

每個階段的最優狀態可以從之前某個階段的某個或某些狀態直接得到這個性質叫做最優子結構;

而不管之前這個狀態是如何得到的這個性質叫做無後效性。

另:其實動態規劃中的最優狀態的說法容易產生誤導,以為只需要計算最優狀態就好,lis問題確實如此,轉移時只用到了每個階段「選」的狀態。但實際上有的問題往往需要對每個階段的所有狀態都算出乙個最優值,然後根據這些最優值再來找最優狀態。比如揹包問題就需要對前i個包(階段)容量為j時(狀態)計算出最大價值。然後在最後乙個階段中的所有狀態種找到最優值。

動態規劃 遞推

hdu2044 1到n的路徑數f n 有兩種 f n 1 的路徑,f n 2 的路徑 編號a到b的蜂房可以看作編號1到b a的蜂房 include using namespace std long long f 55 int n int main int a,b cin n while n retu...

遞迴 遞推 貪心 搜尋和動態規劃

遞迴 函式呼叫自身,直到達到基線條件之後,再一層層的回歸到最初的問題。這是一種自頂向下的方法。動態規劃通常是用遞推 自底向上 來實現的,但是使用備忘錄遞迴 自頂向下 也能夠實現動態規劃。例如,動態規劃 從入門到放棄 結合這篇部落格的例子來理解,詳解動態規劃 鄒博講動態規劃 已知問題規模為n的前提a,...

遞推與遞迴,分治法 貪心 動態規劃的區別

動態規劃 dynamic programming,dp 是一種用來解決一類 最優化問題 的演算法思想。簡單來說,動態規劃將乙個 複雜的問題分解成若干個子問題,通過綜合子問題的最優解來得到原問題的最優解。需要注意的是,動態規劃會將每個求解過的子問題的解記錄下來,這樣當下一次碰到同樣的子問題時,就可以直...