動態規劃題目集合(python)
動態規劃演算法通常用於求解具有某種最優性質的問題.這類題目技巧性較大,如果沒有使用過動態規劃,有時侯會覺得素手無策.動態規劃問題需要找到狀態和狀態轉移方程.困難的地方在於 狀態如何描述 以及 狀態轉移方程如何定義
舉個例子把~如果我們有面值為1元、2元和5元的硬幣若干枚,如何用最少的硬幣湊夠11元?
令d(i) = j表示狀態,表示湊該i元最少需要j個硬幣.如d(i=0) = 0個,d(i=1)=1個,d(i=2)=1個,d(i=3)=2個,d(i=4)=2個...
我們再看看什麼是狀態轉移方程,描述狀態之間是如何轉移的.即d(i)如何根據前面i-1個狀態得到的.
比如i=5的情況,因為是要最小的硬幣數,再拿一枚硬幣就能到的可以是,d(i=4)+1個1塊的,或者d(i=3)+1個2塊的,或者d(i=0)+1個5塊,因為前面狀態都知道,所以呢d(i=5)=min{2+1,2+1,0+1}=1
d(i)=min{ d(i-vj)+1 },其中i-vj >=0,vj表示第j個硬幣的面值.動態規劃就是保留原來的路子,尋找最優的路子,為程式碼如下:
虛擬碼如下:
for j in range(0, K):
d(j) 如何通過j-1個狀態得到(即狀態轉移方程)
總結:
1 明白何時用動態規劃(最優解問題,特別是針對那種,昨天拍大腿定的東西都不作數,還會往前倒翻舊賬)
2 如果可以用,2個步驟
第一步,確定狀態的表示式
第二步,確定狀態轉移方程(可以暴力地把之前所有的轉態都考慮上)
然後再順便考慮以下終止條件之類的,但一般能確定狀態轉移方程,這題就沒問題了。
1 醜數
題目描述
把只包含質因子2、3和5的數稱作醜數(Ugly Number)。例如6、8都是醜數,但14不是,因為它包含質因子7。 習慣上我們把1當做是第一個醜數。求按從小到大的順序的第N個醜數。
解題思路:這個用動態規劃感覺就很好啦
終止條件:第N個醜數
狀態:s[i] 第i個醜數
狀態轉移方程: s[i] = min(s[t1]*2 , s[t2]*3, s[t3]*5)。這個t1,t2,t3<i-1
這3個t怎麼確定呢?從i-1往後倒騰,滿足s[t1-1]*2小於等於s[i-1]但s[t1]*2大於s[i-1]
確定了之後敲程式碼把~~(程式碼還有很多可以優化的,但覺得這個可讀性比較強,貼上自己的程式碼)
class Solution:
def GetUglyNumber_Solution(self, index):
if index<1:
return 0
if index==1:
return 1
s = []
s.append(1)
t1 = 0
t2 = 0
t3 = 0
for i in range(1,index):
for j in range(i):
if s[j]*2 > s[i-1]:
t1 = j
break
for j in range(i):
if s[j]*3 > s[i-1]:
t2 = j
break
for j in range(i):
if s[j]*5 > s[i-1]:
t3 = j
break
s.append(min(s[t1]*2,s[t2]*3,s[t3]*5))
return s[-1]
2 Maximum Subarray(leetcode)
題目描述
Find the contiguous subarray within an array (containing at least one number) which has the largest sum.
For example, given the array [−2,1,−3,4,−1,2,1,−5,4]
,
the contiguous subarray [4,−1,2,1]
has the largest sum = 6
.
(給定一個數組,求最大連續子段和)
解題思路:這個題 是dp經典題啦,將陣列T第i個數最大的和定義為狀態(不是整個陣列最大的),這個和應不應該加前面的,加的話不能比自己本身的值還低。
直接狀態轉移方程把: :sum[i] = max(sum[i-1]+T[i], T[i])
最後返回最大的sun[i]
題比較簡答,程式碼略。