程式設計之美 動態規劃

2021-08-17 16:40:18 字數 2489 閱讀 9775

動態規劃的本質不在於是遞推或是遞迴,也不需要糾結是不是記憶體換時間。

理解動態規劃並不需要數學公式介入,只是完全解釋清楚需要點篇幅…首先需要明白哪些問題不是動態規劃可以解決的,才能明白為神馬需要動態規劃。不過好處時順便也就搞明白了遞推貪心搜尋和動規之間有什麼關係,以及幫助那些總是把動規當成搜尋解的同學建立動規的思路。當然熟悉了之後可以直接根據問題的描述得到思路,如果有需要的話再補充吧。

動態規劃是對於 某一類問題 的解決方法!!重點在於如何鑑定「某一類問題」是動態規劃可解的而不是糾結解決方法是遞迴還是遞推!

怎麼鑑定dp可解的一類問題需要從計算機是怎麼工作的說起…計算機的本質是乙個狀態機,記憶體裡儲存的所有資料構成了當前的狀態,cpu只能利用當前的狀態計算出下乙個狀態(不要糾結硬碟之類的外部儲存,就算考慮他們也只是擴大了狀態的儲存容量而已,並不能改變下乙個狀態只能從當前狀態計算出來這一條鐵律)

當你企圖使用計算機解決乙個問題是,其實就是在思考如何將這個問題表達成狀態(用哪些變數儲存哪些資料)以及如何在狀態中轉移(怎樣根據一些變數計算出另一些變數)。所以所謂的空間複雜度就是為了支援你的計算所必需儲存的狀態最多有多少,所謂時間複雜度就是從初始狀態到達最終狀態中間需要多少步!

太抽象了還是舉個例子吧:

比如說我想計算第100個非波那契數,每乙個非波那契數就是這個問題的乙個狀態,每求乙個新數字只需要之前的兩個狀態。所以同乙個時刻,最多隻需要儲存兩個狀態,空間複雜度就是常數;每計算乙個新狀態所需要的時間也是常數且狀態是線性遞增的,所以時間複雜度也是線性的。

上面這種狀態計算很直接,只需要依照固定的模式從舊狀態計算出新狀態就行(a[i]=a[i-1]+a[i-2]),不需要考慮是不是需要更多的狀態,也不需要選擇哪些舊狀態來計算新狀態。對於這樣的解法,我們叫遞推。

非波那契那個例子過於簡單,以至於讓人忽視了階段的概念,所謂階段是指隨著問題的解決,在同乙個時刻可能會得到的不同狀態的集合。非波那契數列中,每一步會計算得到乙個新數字,所以每個階段只有乙個狀態。想象另外乙個問題情景,假如把你放在乙個圍棋棋盤上的某一點,你每一步只能走一格,因為你可以東南西北隨便走,所以你當你同樣走四步可能會處於很多個不同的位置。從頭開始走了幾步就是第幾個階段,走了n步可能處於的位置稱為乙個狀態,走了這n步所有可能到達的位置的集合就是這個階段下所有可能的狀態。

現在問題來了,有了階段之後,計算新狀態可能會遇到各種奇葩的情況,針對不同的情況,就需要不同的演算法,下面就分情況來說明一下:

假如問題有n個階段,每個階段都有多個狀態,不同階段的狀態數不必相同,乙個階段的乙個狀態可以得到下個階段的所有狀態中的幾個。那我們要計算出最終階段的狀態數自然要經歷之前每個階段的某些狀態。

好訊息是,有時候我們並不需要真的計算所有狀態,比如這樣乙個弱智的棋盤問題:從棋盤的左上角到達右下角最短需要幾步。答案很顯然,用這樣乙個弱智的問題是為了幫助我們理解階段和狀態。某個階段確實可以有多個狀態,正如這個問題中走n步可以走到很多位置一樣。但是同樣n步中,有哪些位置可以讓我們在第n+1步中走的最遠呢?沒錯,正是第n步中走的最遠的位置。換成一句熟悉話叫做「下一步最優是從當前最優得到的」。所以為了計算最終的最優值,只需要儲存每一步的最優值即可,解決符合這種性質的問題的演算法就叫貪心。如果只看最優狀態之間的計算過程是不是和非波那契數列的計算很像?所以計算的方法是遞推。

既然問題都是可以劃分成階段和狀態的。這樣一來我們一下子解決了一大類問題:乙個階段的最優可以由前乙個階段的最優得到。

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

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

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

每個階段的狀態或許不多,但是每個狀態都可以轉移到下一階段的多個狀態,所以解的複雜度就是指數的,因此時間複雜度也是指數的。哦哦,剛剛提到的之前的路線會影響到下一步的選擇,這個令人不開心的情況就叫做有後效性。

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

契機就在於後效性。

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

假裝我們年幼無知想用搜尋去尋找最長上公升子串行。怎麼搜尋呢?需要從頭到尾依次列舉是否選擇當前的數字,每選定乙個數字就要去看看是不是滿足「上公升」的性質,這裡第i個階段就是去思考是否要選擇第i個數,第i個階段有兩個狀態,分別是選和不選。哈哈,依稀出現了剛剛迷宮找路的影子!咦慢著,每次當我決定要選擇當前數字的時候,只需要和之前選定的乙個數字比較就行了!這是和之前迷宮問題的本質不同!這就可以縱容我們不需要記錄之前所有的狀態啊!既然我們的選擇已經不受之前狀態的組合的影響了,那時間複雜度自然也不是指數的了啊!雖然我們不在乎某序列之前都是什麼元素,但我們還是需要這個序列的長度的。所以我們只需要記錄以某個元素結尾的lis長度就好!因此第i個階段的最優解只是由前i-1個階段的最優解得到的,然後就得到了dp方程(感謝

@韓曦指正)

《程式設計之美》買書問題 動態規劃

問題描述 在節假日的時候,書店一般都會做 活動。由於 哈利波特 系列相當暢銷,店長決定通過 活動來回饋讀者。上櫃的 哈利波特 平裝本系列中,一共有五卷。假設每一捲單獨銷售均需8歐元。如果讀者一次購買不同的兩卷,就可以扣除5 的費用,三卷則更多。假設具體折扣的情況如下 本數 折扣 2 5 3 10 4...

程式設計之美 買書問題 動態規劃

一,問題 上櫃的 哈利波特 平裝本系列,一共有五卷。假設每一捲單獨銷售均需8歐元。如果讀者一次購買不同的兩卷,就可以扣除5 的費用,三卷則更多。假設具體折扣的情況如下 本數2 折扣 5 本數3折扣 10 本數4折扣 20 本數 5 折扣25 問題 設計出演算法,能夠計算出讀者所購買的一批書的最低 二...

推薦《程式設計之美》

推薦 程式設計之美 我很早知道鄒欣計畫要寫這樣一本書,也能夠預計到這本書定會廣受歡迎,因為它符合當前大量求職人員的需求,畢竟於他們而言,誰不想知道微軟亞洲研究院在招人時候問些什麼問題呢。另一方面,把考察軟體技術人員專業知識和相應技能的各種手段加以歸納和整理,這本身也是對業界的貢獻,所以,我相信,一旦...