今天是乙個大晴天,不想學習就來碼一下字,謝謝娜娜提醒
動態規劃的本質不在於是遞推或者遞迴,也不需要糾結是不是記憶體換時間
理解動態規劃並不需要數學公式的介入,只是完全解釋清楚需要點篇幅
首先需要明白哪些問題不是動態規劃可以解決的,才能明白為什麼需要動態規劃。不過好處就是順便搞明白了遞推貪心搜尋和動態規劃之間有什麼關係,以及幫助那些總是把動態規劃當成搜尋解的同學建立動態規劃的思路。當然熟悉了之後可以直接根據問題的描述得到思路,如果有需要的話再補充吧
動態規劃是對某一類問題的解決方法、重點在於如何鑑定「某一類問題」是動態規劃可解的而不是糾結解決方法是遞迴還是遞推!
怎麼鑑定動態規劃問題可解的,這需要從計算機是怎麼工作的說起:計算機的本質是乙個狀態機,記憶體裡儲存的所有資料構成了當前的狀態,cpu只能利用當前狀態計算處下乙個狀態
當你企圖使用計算機解決乙個問題是,其實就是在思考如何將這個問題表達成狀態(用哪些變數儲存哪些資料)以及如何在狀態中轉移(怎樣根據一些變數計算出另一些變數)。所以所謂的空間複雜度就是為了支援你的計算所必須儲存的狀態最多有多少,所謂的時間複雜度就是從初始狀態到達最終狀態中間需要多少步!!
太抽象了,還是幾個舉個例子吧
比如說我想計算100個斐波那契數,每乙個斐波那契數就是這個問題的乙個狀態,每求乙個新數字只需要儲存兩個狀態。所以同一時刻,最多隻需要儲存兩個狀態,空間複雜度是常數;每計算乙個新狀態所需要的時間也是常數且狀態也是線性遞增的,所以時間複雜度也是線性的。
上面這種狀態計算很直接,只需要依照固定的模式從舊狀態計算出新狀態就行(a[i]=a[i-1]+a[i-2]),不需要考慮是不是需要更多的狀態,也不需要選擇哪些舊莊台來計算新狀態。對於這樣的解法,我們叫遞推。
菲波那切數列那個例子過於簡單,以至於讓人忽略了階段的概念,所謂階段是指隨著問題的解決,在同一時刻可能會得到的不同狀態的集合。在菲波那切數列中,每一步計算會得到乙個新數字,所以每個階段只有乙個狀態。想象另外乙個問題的情景,例如把你放在乙個圍棋棋盤上的某乙個點,你每一步只能走一格,因為你可以東南西北隨便走,所以你當你同樣走四步可能會處於很多個不同的位置。從頭開始走了幾步就是第幾個階段,走了這n步所有可能到達的位置的集合就是這個就是這個階段下所有可能的狀態。
現在問題來了,有了階段之後,計算新狀態可能會遇到各種奇葩的情況,針對不同的情況,就需要用不同的演算法,下面就分情況來說明一下:
假如問題有n個階段,每個階段都有多個狀態。不同階段的狀態數目不必相同,乙個階段的乙個狀態可以得到下個階段的所有狀態中的幾個。那我們要計算出最終階段的狀態數目自然要經歷之前每個階段的某些狀態。
好訊息是,有時候我們並不需要真的計算所有狀態,比如這樣乙個弱智的棋盤問題:從棋盤的左上角到達右下角最短需要幾步。答案很顯然,用這樣乙個弱智的問題是為了幫助我們理解階段和狀態。某個階段確實可以有多個狀態,正如這個問題中走n步可以走到很多位置一樣。但是同樣n步中,有哪些位置可以讓我們在第n+1步中走的更遠呢?沒錯,正是第n步中走的更遠的位置。換成一句熟悉的話叫做「下一步最優是從當前最優得到的」。所以為了計算最終的最優值,只需要儲存每一步的最優值即可,解決符合這種性質的問題的演算法叫做貪心。如果只看最優狀態之間的計算過程是不是和菲波那切數列的計算很像?所以計算的方法就是遞推。
既然問題都是可以劃分成階段和狀態的。這樣一來我們一下子就解決了一大類問題:乙個階段的最優可以由前乙個階段的最優得到。
如果乙個階段的最優無法用前乙個階段的最優得到呢?
什麼?你說只需要之前兩個階段就可以得到當前最優?那跟只用前乙個階段並沒有本質區別。最麻煩的情況在於你需要之前的所有情況才行。
再來乙個迷宮的例子。在計算從起點到終點的最短路線時,你不能只儲存當前階段的狀態,因為題目要求你最短,所以你必須知道之前走過的所有位置。因為即便你當前在的位置不變,之前的路線不同會影響你之後的路線。這時你需要儲存的是之前每個階段所經歷的那個狀態,根據這些資訊才能計算出下乙個狀態。
每個階段的狀態或許不多,但是每個狀態都可以轉移到下一階段的多個狀態,所以解的複雜度就是指數的,因此時間複雜度也是指數的。辣麼,剛剛提到的之前的路線會影響到下一步的選擇,這個令人不開心的情況叫做後效性。
剛剛的情況實在太普遍,解決方法實現太暴力,有沒有哪些情況可以避免如此暴力呢?
契機就在於後效性
有一類問題,看似需要之前的所狀態,其實不用,不妨也是那最長上公升子串行的例子來說明為什麼它不需要暴力搜尋,進而引出動態規劃的思路。
假裝我們年幼無知想用搜尋去尋找最長上公升子串行。怎麼搜尋呢?需要從頭到尾依次列舉是否選擇當前的數字,每選定乙個數字就要去看看是不是滿足「上公升」的性質,這裡第i個階段就是去思考要不要選擇第i個數,第i個階段有兩個狀態,分別是選和不選。哈哈,依稀出現了剛剛迷宮找路的影子!咦,慢著,每次當我決定要選擇當前數字的時候,只需要和之前選定的數字進行比較就行了!這是和之前迷宮問題的本質不同! 這就可以縱容我們不需要記錄之前的所有狀態啦!既然我們的選擇已經不受之前狀態組合的影響了,那時間複雜度也就自然不是指數的了哦!雖然我們不在乎某序列之前是什麼元素,但是我們還是需要這個序列的長度的。所以我們只需要記錄以某個元素結尾的lis長度就好!因此第i個階段的最優解只是由前i-1個階段的最優解得到的,然後就得到了dp方程
lis = max jand a[j]所以乙個問題是該用遞推、貪心、搜尋還是動態規劃,完全是由這和問題本身階段間狀態的轉移方式決定的!!!!啦啦啦啦,到這裡忽然豁然開朗
每個階段只有乙個狀態—————————————————————————————->遞推
每個階段的最優狀態都是上乙個狀態的最優狀態得到的——————————————————–>貪心
每個階段的最優狀態是由之前所有階段的狀態的組合得到的—————————————————>搜尋
每個階段的最優狀態可以從之前某個階段的某個或某些狀態直接得到而不管之前這個狀態是如何得到的——->動態規劃
每個階段的最優狀態可以從之前某個階段的某個或某些狀態直接得到 ——————-這個性質叫做最優子結構
而不管這個狀態是如何得到的————————————————————這個性質叫做無後效性
tips:其實動態規劃中的最優狀態的說法容易產生誤導,以為只需要計算最優狀態就好,lis問題確實如此,轉移時只用到了每個階段「選」的狀態。但實際上有的問題需要對每個階段的所有狀態都計算出最優值,然後根據這些最優值在來找最優狀態。比如揹包問題就需要對前i個揹包(階段)容量為j時(狀態)計算出最大價值。然後在最後乙個階段中的所有狀態中找到最優值。
下一節來寫一寫,0-1揹包問題!!今天寫到這裡,睡覺去!
這是我搬過來的,出處:
動態規劃 什麼是動態規劃?
先來看看 資訊學奧賽一本通第5版 是怎麼說的 動態規劃程式設計是對解最優化問題的一種途徑 一種方法,而不是一種特殊演算法。不像前面所述的那些搜尋或數值計算那樣,具有乙個標準的數學表示式和明確清晰的解題方法。動態規劃程式設計往往是針對一種最優化問題,由於各種問題的性質不同,確定最優解的條件也互不相同,...
mysql動態規劃 動態規劃
動態規劃 能夠動態規劃的問題具有以下特點 可分解成規模更小的子問題 子問題的結果可復用 關鍵是要理解狀態轉移方程的含義就好啦!數字三角形 問題描述 在數字三角形尋找從頂到底的路徑,使得路徑經過的數字之和最大。規定每一步只能往左下或右下走,求出最大路徑和。遞迴解法 include include us...
《動態規劃》 ACM 動態規劃例題詳解
描述 7 3 8 8 1 0 2 7 4 4 4 5 2 6 5 圖1 圖1給出了乙個數字三角形。從三角形的頂部到底部有很多條不同的路徑。對於每條路徑,把路徑上面的數加起來可以得到乙個和,你的任務就是找到最大的和。注意 路徑上的每一步只能從乙個數走到下一層上和它最近的左邊的那個數或者右邊的那個數。輸...