1. 程式人生 > >動態規劃題目集合(python)

動態規劃題目集合(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]

題比較簡答,程式碼略。