動態規劃算法(DP)

    校招筆試面試前,大家一般都會先去牛客網上刷刷題,《劍指offer》,《leetcode》走起來,然後初次入手,發現很多不會,不會到什麼程度呢,連個想法都沒有,於是就去討論區看答案,然後java大神,c++大神會給出花式解答,他們喜歡在答案前加一句,簡單的dp算法,遞歸就可以解決,巴拉巴拉。說的還是很詳細的,然而代碼並不能看懂,畢竟

    人生苦短,我用python

下面就先給大家舉一些詳細的例子來說說如何解決動態規劃問題

    首先,你要知道什麼才能算動態規劃問題,這裏,推薦《算法圖解》這本書,是基於python寫的一本算法講解書,內容非常簡單,沒未接觸過算法的人也能看懂,我先直接引用這裏的講法:












動態規劃就是要將問題細分爲小問題,然後再着手解決這些小問題。

例1:(題目來源於牛客網)

題目描述

給你六種面額1、5、10、20、50、100元的紙幣,假設每種幣值的數量都足夠多,編寫程序求組成N員(N爲0-10000的非負整數)的不同組合的個數。

輸入描述:

輸入爲一個數字N,即需要拼湊的面額

輸出描述:

輸出也是一個數字,爲組成N的組合個數。

這可以視爲一個動態迴歸問題解決,首先我們可以畫一個dp表格

dp表的列數字表示要拼成的面額,行表示可以用哪幾種面額的拼,比如說dp的一元行,5元列表示只用一元錢拼成5元錢只有一種方法,dp1元,5元行、6元列表示用幣值1元和5元拼成6元的方法有兩種,明顯dp[1,:]=1,而若j>i,dp[i,j]=dp[i-1,j]+dp[i,j-i],例如dp[2,10]=dp[1,10]+dp[2,5], 這個表達式說明,用1元和5元的面額拼成10元的方法數=用1元拼成10元的方法數+用1元和5元拼成5元的方法數,因爲面額6-9元拼成方法都是一樣的,暫時沒有更小的面額可供選擇,這個公式便是這個算法的核心

dp表格
 012345678910
1元11111111111
1元,5元11111222223
1,元,5元,10元11111222224
1,5,10,20元           
,1,5,10,20,50元           
,1,5,10,20,50,100元           

代碼如下

money=[1,5,10,20,50,100]
n = int(input())
li=[]
for i in range(n+1):
    li.append(0)
li[0]=1
for i in money:
    for j in range(n+1):
        if j>=i:
            li[j]=li[j]+li[j-i]
    print(li)
例2 來源於《劍指offer》

題目描述

HZ偶爾會拿些專業問題來忽悠那些非計算機專業的同學。今天測試組開完會後,他又發話了:在古老的一維模式識別中,常常需要計算連續子向量的最大和,當向量全爲正數的時候,問題很好解決。但是,如果向量中包含負數,是否應該包含某個負數,並期望旁邊的正數會彌補它呢?例如:{6,-3,-2,7,-15,1,2,2},連續子向量的最大和爲8(從第0個開始,到第3個爲止)。你會不會被他忽悠住?(子向量的長度至少是1)

簡單來說就是求一個最大子串問題,也是一個典型的動態規劃問題

思路:設F(i)是以array[i]爲結束點的最大子向量(從0開始),比如說F(3)就是最後一個向量是7的最大子串,可知

          F(i) = max(F(i-1)+array[i],array[i])

          設res是所有字串中最大的那個,也就是我們最後要求的值

          res  = max(res,F(i))

代碼:

def FindGreatestSumOfSubArray(array):
        f = array[0]
        res = array[0]
        for i in range(1,len(array)):
            f = max(f+array[i],array[i])
            res = max(res,f)
        return res
這樣便求得最後的解,不懂的話可以自己手寫一下循環,多悟幾次,日後使用起來就很方便啦


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章