1. 程式人生 > >動態規劃python版

動態規劃python版

一 動態規劃

動態規劃問題是面試題中的熱門話題,如果要求一個問題的最優解(通常是最大值或者最小值),而且該問題能夠分解成若干個子問題,並且小問題之間也存在重疊的子問題,則考慮採用動態規劃。

使用動態規劃特徵:  1. 求一個問題的最優解  2. 大問題可以分解為子問題,子問題還有重疊的更小的子問題  3. 整體問題最優解取決於子問題的最優解(狀態轉移方程)  4. 從上往下分析問題,從下往上解決問題  5. 討論底層的邊界問題

例項1  剪繩子問題  給你一根長度為N的繩子,請把繩子剪成M段(m,n都是整數),每段繩子的  長度記為k[0],k[1],k[2]…. 請問如何剪繩子使得k[0],k[1],k[2]  的乘積最大  例如 繩子長度8 最大乘積18 = 2*3*3

def jianshengzi(n):
    # 先對邊界問題進行求解,因為明顯剪的值小於不剪的值
    # 則提出先討論這三種情況
    if n < 2:
        return 0
    if n == 2:
        return 1    #長度為2,只能剪成1*1
    if n == 3:
        return 2    #長度為3,剪成2*1 > 1*1*1

    #若繩子長於4呢,申請一個長度為50的陣列
    #羅列出切割的邊界問題

    h = [0]*50
    h[0] = 0
    h[1] = 1
    h[2] = 2
    h[3] = 3
    # 遞迴問題是 f(n) = max{f(i)*f(n-i)}
    for i in range(4,n+1):
        maxs = 0
        for j in range(1,i/2+1):
            mult = h[j] * h[i-j]
            if maxs < mult:
                maxs = mult
            h[i] = maxs     # 每次J的迭代輪詢出該長度的最大值
    print h
    return h[n]

print jianshengzi(8)

例項2  硬幣問題  我們有面值為1元3元5元的硬幣若干枚,如何用最少的硬幣湊夠11元?  分析:  1 求問題的最優解:最小的硬幣數  2 是否有子問題:f(n)表示的最少硬幣數是是上一次拿時候的硬幣數最少。  注意:f(n)是n元的最小硬幣數,最後一次可拿的硬幣數為1,3,5 則下一步  的最小硬幣數為 f(n-vi) 它的狀態變更不是按元數的,是按照上次拿的硬幣錢目  3 狀態轉移方程為 f(n)= min(f(n-vi)+1)  4 邊界問題(找到最後一個重複的問題) 這裡  f(1)=1 ,f(2)=f(1)+f(1)=2 f(3)=min(1,f(2)+1)  f(4)=f(3)+1 f(5)=1  5 從上往下分析問題,從下往上解決問題。

def f(n):
    if n == 1:      #把所有的邊界問題找到
        return 1
    if n == 2:
        return 2
    if n == 3:
        return 1
    if n == 4:
        return 2
    if n == 5:
        return 1

    h = [1,3,5]
    minx = n
    for i in range(3):
        coun = f(n-h[i])+1    # 採用了遞迴的思想 這裡是從上到下,
        if minx > coun:       # 複雜度比較高
            minx = coun
    return minx

print f(11)
def f(n):
    if n == 1:
        return 1
    if n == 2:
        return 2
    if n == 3:
        return 1
    if n == 4:
        return 2
    if n == 5:
        return 1

    h = [1,3,5]
    for x in range(6,n+1):     #從下往上的思維解決
        minx = n
        for i in range(3):      
            coun = f(x-h[i])+1   #從下往上的思維解決 
            if minx > coun:
                minx = coun
    return minx
print f(11)