有n
件物品和乙個容量為v
的揹包。第i
件物品的費用是w[i]
,價值是v[i]
,求將哪些物品裝入揹包可使價值總和最大。
定義陣列
dp[i]
[j] # 代表前i個商品,放入乙個容量為j的揹包,所獲得的最大價值
初始化
# 如果要求恰好放滿揹包,則陣列初始化為 -inf
dp =[[
-inf]
*(amount +1)
for _ in range
(n)]
# 如果要求恰好放滿揹包,則陣列初始化為 0
dp =[[
0]*(amount +1)
for _ in range
(n)]
需要格外強調的是:第
一、無論初始化是如何進行的,但是我們每次迭代商品的時候:dp[i][0]一定要等於0
,因為放滿容量為0
的揹包,價值肯定是0
。第
二、動態陣列的長度是(容量+1)
(要考慮容量為0的情形)。
轉移方程
for i in range
(n+1
): # 初始化工作對i==
0的時候已經做了處理,所以這裡可以不用再考慮。
for j in range
(w[i]
,v+1
): # 正序
f[i]
[j]=
max(f[i−1
][j]
,f[i−1
][j−w[i]
]+v[i]
)
我們觀察轉移方程:
f[i]
[j]=
max(f[i−1
][j]
,f[i−1
][j−w[i]
]+v[i]
)
發現f[i][j]
只和上一行正上方
和上一行的左上方
有關。如果我們只用一行資料正序遍歷的話,我們會將上一行左上方
的資料先覆蓋掉。所以我們採用逆序遍歷。
def package_01
(size, values, weights)
:# dp[j]代表裝滿容量為j的揹包能產生的最大價值
import numpy
# 如果不要求完全裝滿
dp = numpy.
array([
0]*(size +1)
) # 如果要求完全裝滿
# dp = [-float("inf")] * (size + 1)
# 初始化,無論是要求裝滿還是不裝滿,初始化規則一樣,只是如果要求不裝滿,已經是0,可以省略初始化條件
dp[0]
=0for i in range
(len
(values)):
for j in range
(size, weights[i]-1
,-1)
: # 逆序
dp[j]
=max
(dp[j]
, dp[j - weights[i]
]+ values[i]
)return dp[size]
有n
種商品和乙個容量為v
的揹包。第i
件物品有無數件,且費用是w[i]
,價值是v[i]
,求將哪些物品裝入揹包可使價值總和最大。
完全揹包和01揹包的邏輯基本類似,但是由於物品可以任意次取,所以我們每個物品取用多少次 取決於當0<=k*w[i]<=j
時,f[i−1][j−k*w[i]]+k*v[i]
最大。
f[i]
[j]=
max(f[i−1
][j−k*w[i]
]+k*v[i])0
<=k*w[i]
<=j
將上面的邏輯轉為程式語言
k =
1while k * weights[i]
<= j:
dp[i]
[j]=
max(dp[i]
[j], dp[i -1]
[j - k * weights[i]
]+ k * weights[i]
) k +
=1
最終解法:
def package_total
(size, values, weights)
: import numpy
# 如果不要求完全裝滿
dp = numpy.
array([
[0]*
(size +1)
for _ in range
(len
(values))]
) # 初始化,無論是要求裝滿還是不裝滿,初始化規則一樣,只是如果要求不裝滿,已經是0,可以省略初始化條件
dp[0]
[0]=
0for i in range
(len
(values)):
for j in range
(weights[i]
, size +1)
: k =
1while k * weights[i]
<= j:
dp[i]
[j]=
max(dp[i]
[j], dp[i -1]
[j - k * weights[i]
]+ k * weights[i]
) k +=1
return dp[-1
][-1
]
def package_total
(size, values, weights)
:# dp[j]代表裝滿容量為j的揹包能產生的最大價值
import numpy
# 如果不要求完全裝滿
dp = numpy.
array([
0]*(size +1)
) # 如果要求完全裝滿
# dp = [-float("inf")] * (size + 1)
# 初始化,無論是要求裝滿還是不裝滿,初始化規則一樣,只是如果要求不裝滿,已經是0,可以省略初始化條件
dp[0]
=0for i in range
(len
(values)):
for j in range
(weights[i]
, size +1)
: # 正序
dp[j]
=max
(dp[j]
, dp[j - weights[i]
]+ values[i]
)return dp[size]
Leetcode揹包問題
題意 幾種無限數量的硬幣,湊成amount的方案數,方案是無序的,即1 2 和 2 1算同一種 題解 方法一 經典揹包解法 dp i j 表示前i個物品湊出j的方案數,考慮第i個選與不選兩種情況,其中選的時候,再考慮選擇第i個物品的次數。class solution return dp n amou...
Leetcode 0 1揹包問題
什麼是揹包問題?比如有n個物品,它們有各自的體積和價值,現有給定容量的揹包,如何讓揹包裡裝入的物品具有最大的價值總和?0 1揹包問題就是這n個物品中某乙個物品選還是不選,分別表示1和0 題目描述 比如有n個物品,它們有各自的體積w和價值v,現有給定容量的揹包ba 如何讓揹包裡裝入的物品具有最大的價值...
揹包問題 01揹包問題
n個物品,總體積是v,每個物品的體積的vi,每個物品的最大價值是wi,在不超過v的體積下求最大價值 eg揹包容積為 5 物品數量為 4 物品的體積分別為 物品的價值分別為 思路定義乙個二位陣列int f new int n 1 v 1 f i j 就表示在1 i個物品中選取體積小於v的情況的最大價值...