微信公衆號:Jerry的算法和NLP算法
揹包問題是一個經典的動態規劃模型。它既簡單形象容易理解,又在某種程度上可以揭示動態規劃的本質,故很多教材都把它做爲動態規劃部分的第一道例題.數組
4 6 1 2 3 2 4 1 3 4 3 4 5 2
10
與零一揹包不一樣的是,零一揹包中的物品是不能夠重複拿取的,只能夠拿取當前物品或者不拿取當前物品,不能夠拿取多個,徹底揹包的物品是能夠任意拿取多個的來構成不超過揹包容量而且構成的總價值是最大的.微信
而這道題是多重揹包問題,也就是這個物品的個數是有限個的,在物品個數範圍內能夠任意選擇app
動態規劃的核心是找到dp公式或者狀態轉移的方程,理解清楚中間的過程是怎麼樣進行變化的,由於動態規劃老是要利用到以前上一個物品選擇後的最佳方案,因此dp數組裏面存儲的確定是歷史上存儲的最佳方案,一開始的時候咱們是能夠藉助excel表格來幫助咱們理解dp數組是怎樣生成的ide
創建一個二維數組f[i][j],定義爲i爲遍歷到第i個物品的時候,j爲揹包的容量大小,j最大爲m,如f[2][3]指的就是遍歷到第二個物品下容量爲3的最大價值
首先先遍歷物品,再遍歷容量。
因爲每一個物品的個數都不同,因此咱們還要遍歷一下物品個數,看看物品是否都能放入揹包中。3d
假設如今第一個物品的輸入是1 2 3 表明着 體積爲1 ,價值爲2, 物品數量爲3。
那麼首先咱們的嵌套第一層循環爲物品 ,第二層循環爲體積 ,第三層循環爲物品數量 ,看看當前若是是這麼多的物品能不能同時放入揹包中 。excel
僞代碼爲code
1for i 遍歷物品 2 for j 遍歷體積 從小到大 3 for k 遍歷當前物品個數 4 當k*體積<=揹包容量的時候 說明咱們的揹包是能夠放下這麼多物品的 5 dp[i][j]=max ( dp[i-1][j-k*wi]+k*vi , dp[i-1[j]) 6 這個表達式的意思就是 要麼選擇K個這樣的物品,要麼不選,看看哪一個是最優的解,而後更新便可 7 8 當k*體積<揹包容量的時候說明咱們的揹包是放不下這麼多物品的 9 直接就是dp[i][j]=dp[i-1][j]
更新第一輪以後表格變化爲blog
第二個物品更新完後是這樣的input
到最後直接輸出dp[-1][-1]便可 表明着遍歷到最後一個物品 最大容量下的最優解
1a=input() 2N,V=list(map(int,a.split())) 3w=[0] 4v=[0] 5s=[0] 6for i in range(N): 7 b=input() 8 wi,vi,si=list(map(int,b.split())) 9 w.append(wi) 10 v.append(vi) 11 s.append(si) 12 13dp=[[0 for i in range(V+1)]for i in range(N+1)] 14for i in range(V,-1,-1): 15 for j in range(s[1],0,-1): 16 if i>=j*w[1]: 17 dp[1][i]=max(dp[1][i-j*w[1]]+j*v[1],dp[1][i]) 18 19for i in range(2,N+1): 20 for j in range(V+1): 21 for k in range(s[i]+1): 22 if j>=k*w[i]: 23 dp[i][j]=max(dp[i-1][j-w[i]*k]+v[i]*k,dp[i][j]) 24 else: 25 dp[i][j]=max(dp[i-1][j],dp[i][j]) 26print(dp[-1][-1])
2020大廠筆試 | 網易提早批(1)
2020大廠筆試 | 網易提早批(2)
使人頭疼的揹包九講(1)0/1揹包
使人頭疼的揹包九講(2)徹底揹包
騰訊筆試的幾道題