一、什麼是動態規劃?
動態規劃演算法通常基於乙個遞推公式及乙個或多個初始狀態。當前子問題的解將由上一次子問題的解推出。使用動態規劃來解題只需要多項式的時間複雜度。
二、例子講解
首先,我們要找到某個狀態的最優解,然後在它的幫助下,找到下乙個狀態的最優解。
用leetcode上的198題house robber作為乙個入門例子吧。
題目的大意是:你是乙個專業的江洋大盜要盜竊一條街道上的房屋裡的財寶。每個房屋都有一定數量的財寶。唯一的限制條件是:任意相鄰的兩個房屋都有乙個互聯的安全系統,如果你同時盜竊相鄰的兩個房屋那麼安全系統會自動報警。在不驚動警察的前提下,算出你今晚能盜竊到的最大的財寶數。用陣列nums儲存每個房屋的財寶,nums[i]表示第i間房屋的財寶。
用動態規劃的思想,將乙個子問題用上乙個子問題的解來表示。對於第i 間房屋,你有兩種選擇:盜竊和不盜竊。(1)如果要盜竊第i間房屋,那麼必定不能盜竊第i-1間房屋,因為會報警,所以收益就等於在判斷第i-2間房屋時候得到的最大收益+第i間房屋的財寶。(2)如果不盜竊第i間房屋,最大收益等於判斷第i-1間房屋時的最大收益。
我們不妨用dp[i] 表示在判斷第i間房屋時得到的最大收益,rob[i]表示盜竊第i間房屋。
那麼轉換方程是:dp[i] = max(dp[i-2]+nums[i], dp[i-1])
有了轉換方程,接下來只需要對其進行初始化即可。易知:dp[0] = 0, dp[1] = nums[0]。有了狀態和狀態轉移方程,這個問題基本上也就解決了。
因此c++**如下:
class solution
return dp[len];
}};
類似的還有leetcode上的121題:best time to buy and sell stock。
另一類動態規劃的題像leetcode上的377題:combination sum iv。
題意:給你乙個整數序列,序列中的數均為正數且沒有重複的,找出所有可能的組合使得它們加起來等於target。
example:
nums
= [1, 2, 3]
target
= 4
the possible combination ways are:
(1, 1, 1, 1)
(1, 1, 2)
(1, 2, 1)
(1, 3)
(2, 1, 1)
(2, 2)
(3, 1)
note that different sequences are countedas different combinations.
therefore the output is7.
使用動態規劃的思想,將乙個子問題用前乙個子問題的解來表示。不妨設dp[i] 表示當target=i 時一共有多少種組合情況。假設可以拆分的整數序列為nums,那麼第一種情況就是將target 拆分成nums[0]和target-nums[0]兩部分,那麼第一種情況的組合數量為dp[target-nums[0]];第二種情況是將target拆分成nums[1]和target-nums[1],那麼第二種情況的組合數量為dp[target-nums[1]]....,以此類
推, dp[target]=
dp[target-nums[0]]+dp[target-nums[1]]+dp[target-nums[2]]+...+dp[target-nums[n-1],
n=nums.size()
有了狀態轉移方程後,要思考初始化情況, dp[0]=1。
於是c++**如下:
class solution
}//for
return dp[target];
}};
動態規劃的問題總結
1 dp 個數 weight 例子 poj 1837 balance dp i w relate to dp i 1 w c j 這道題中dp儲存的不是weight,而是方法個數 include include include include include include define maxnu...
經典動態規劃問題總結
動態規劃引入 首先我們以乙個最基本的例子來分析 菲波那切數列。我們都知道,菲波那切數列的遞推公式f n f n 1 f n 2 這裡我就說明一般情況,不列舉邊界條件了 很簡單,如果我們用遞迴的方法來求解f n 兩三行 就出來了。那麼我們深入分析一下這樣有什麼問題?f 2 f 1 f 0 f 3 f ...
動態規劃經典問題總結
假設有幾種硬幣,如1 3 5,並且數量無限。請找出能夠組成某個數目的找零所使用最少的硬幣數。這是一道經典的動態規劃方法,我們可以維護乙個一維動態陣列dp,其中dp i 表示錢數為i時的最小硬幣數的找零,遞推式為 dp i min dp i dp i coins j 1 其中coins j 為第j個硬...