【學習筆記】dp入門


知識點

動態規划(簡稱dp),可以說是各種程序設計中遇到的第一個坎吧,這篇博文是我對dp的一點點理解,希望可以幫助更多人dp入門。

 

先看看這段話

動態規划(dynamic programming)是運籌學的一個分支,是求解決策過程(decision process)最優化的數學方法。20世紀50年代初美國數學家R.E.Bellman等人在研究多階段決策過程(multistep decision process)的優化問題時,提出了著名的最優化原理(principle of optimality),把多階段過程轉化為一系列單階段問題,利用各階段之間的關系,逐個求解,創立了解決這類過程優化問題的新方法——動態規划。1957年出版了他的名著《Dynamic Programming》,這是該領域的第一本著作。

這是百度百科上對於動態規划介紹,其實dp並沒有這么復雜,可以把dp看作是記憶化搜索的遞推形式。

再來看一下下面這段文字(來自《挑戰程序設計競賽(第二版)》):

 

 

就像上面所說的,對於一道題目,如果選擇搜索可能會出現大量重復的狀態,如函數f

 int f(int a,int b)
 {
     return f(a+1,b+1)+f(a-1,b-1);
 }

 

這種函數在計算過程中有大量的資源被浪費,如 f(1,1) 和 f(3,3) 在返回值時都會計算一次 f(2,2),這種無謂的計算致使了動態規划的誕生。

 

動態規划算法通常基於一個遞推公式及一個或多個初始狀態。當前子問題的解將由上一次子問題的解推出。使用動態規划來解題只需要多項式時間復雜度,因此它比回溯法、暴力法等要快許多。

現在讓我們通過一個例子來了解一下DP的基本原理。

首先,我們要找到某個狀態的最優解,然后在它的幫助下,找到下一個狀態的最優解。

 

(上面這段話看不懂也就別看了)

 其實簡單的來說,dp就是用數組來遞推下一個狀態。

像上面的f函數,寫成dp就是 f[a][b] 。遞推式也與函數基本相同:f[a][b]=f[a-1][b-1]+f[a+1][b+1]。用這個式子,雙重循環即可。

 


 

例題

如下是幾個經典問題,對於初學者來說有一點點難度,不懂可以多看幾篇關於dp入門的文章。此處附上我的代碼。題目可以百度。

最好要理解,並能獨立實現代碼

1、01背包

View Code

2、最長上升子序列(簡稱LIS,兩種做法,一種是O(n2),另一種是O(nlogn))

View Code

3、最長公共子序列(簡稱LCS)

View Code


 

看完了上面的,可以做做題練練手了。

下面是一些題目的練習,題目都在www.luogu.org上,可以配合里面的題解與我的代碼來理解。


 

習題

下述題目都為基礎的dp包括經典問題與其各種變形,乃dp入門必備之題。

注意: 1、從最下面往上刷

 


 

 最后提供一些練習題與詳解:傳送門

刷完了進入下一章:dp基礎

 

洛谷P1280 尼克的任務

逆序dp,詳見注釋

View Code

 

洛谷P1091 合唱隊形

從頭開始,從尾開始各跑一次LIS

View Code

 

洛谷P1115 最大子段和 dp

View Code

 

洛谷P1508 Likecloud-吃、吃、吃

View Code

 

洛谷P1510 精衛填海

View Code

 

洛谷P1855 榨取kkksc03

View Code

 

洛谷P1216 [USACO1.5]數字三角形 Number Triangles

View Code

 

 洛谷P1910 L國的戰斗之間諜

View Code

 

洛谷P2925 [USACO08DEC]干草出售Hay For Sale

View Code

 

洛谷P2347 砝碼稱重

View Code

 

洛谷P2722 總分 Score Inflation

View Code

開始dp入門的征程吧! 

------------------------------------------------------------------------------------------

后繼章:dp基礎


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM