動態規划算法python實現


一、什么是動態規划

動態規划(dynamic programming)是運籌學的一個分支,是求解決策過程(decision process)最優化的數學方法。把多階段過程轉化為一系列單階段問題,利用各階段之間的關系,逐個求解,創立了解決這類過程優化問題的新方法——動態規划。

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

動態規划最重要的有三個概念:1、最優子結構 2、邊界 3、狀態轉移方程

二、走樓梯問題

有十個台階,從上往下走,一次只能走一個或兩個台階,請問總共有多少種走法?

1、最優子結構:我們來考慮要走到第十個台階的最后一步,最后一步必須走到第八或者第九。不難得到 f(10) = f(9)+f(8)。f(9) = f(8)+f(7)

2、邊界:f(1) = 1, f(2) = 2

3、狀態轉移:f(n) = f(n-1) + f(n-2)

解法一:遞歸

def get_count(n):
    if n == 1:return 1
    if n == 2:return 2
    else:
        return get_count(n-1)+get_count(n-2)
print(get_count(10))

程序簡單,但是非常暴力! 

程序復雜度分析:

很顯然這是一個滿二叉樹,高度為N-1。所以總節點數為2^N-1,時間復雜度為O(2^N) 。看着就恐怖。

解法二、備忘錄算法

回顧一下上面的遞歸計算方法,我們不難看出,本來總共只有f(1)-f(N)個節點,硬生生被增加到2^N-1個,這就是產生了大量重復的運算。找到問題的根源,對應的解決方法就應運而生,那就是從下往上算,把以前計算過的數值,保存在一個哈希表中,然后后面計算時先查詢一下,存在就無需計算。時間復雜度為O(n) ,空間復雜度為O(n)。但是在仔細一想其實,無需保存所有的f,每個f都只與前兩個值相關,所以空間復雜度可以降低為O(1).我們來看看相關代碼。

def get_count(n):
    if n == 1:return 1
    elif n == 2 :return 2
    else:
        l = [1,2]
        for i in range(3,n):
            l[0],l[1] = l[1],l[0]+l[1]
        return l[0]+l[1]

 三、整數拆分

def func(n):
    l = [1]
    for i in range(3,n+1):
        m = 0
        for j in range(1,i//2+1):
            m = max(m,j*(i-j),j*l[i-j-2])
        l.append(m)
    return l
print(func(10))

 

 四、最大子序和

核心思想:記錄以前一個數結尾的最長子序列的最大值。

 

def max_subarry(nums):
    m = nums[0]
    tem_m = nums[0]
    pre = nums[0]
    for i in range(1,len(nums)):
        if pre<=0:
            tem_m = nums[i]
            pre = nums[i]
        else:
            pre+=nums[i]
            tem_m+=nums[i]
        if tem_m>m: m = tem_m
    return m

 


免責聲明!

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



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