0-1揹包問題。
dp陣列中dp[i][w]的含義。
dp[i][w]的定義如下:對於前i個物品,當前揹包的容量為w,這種情況下可以裝的最大價值是dp[i][w]。
如果你沒有把這第i個物品裝入揹包,那麼很顯然,最大價值dp[i][w]應該等於dp[i-1][w]。
如果你把這第i個物品裝入了揹包,那麼dp[i][w]應該等於dp[i-1][w-wt[i-1]] + val[i-1]。
首先,由於i是從 1 開始的,所以對val和wt的取值是i-1。
而dp[i-1][w-wt[i-1]]也很好理解:你如果想裝第i個物品,你怎麼計算這時候的最大價值?
換句話說,在裝第i個物品的前提下,揹包能裝的最大價值是多少?
顯然,你應該尋求剩餘重量w-wt[i-1]限制下能裝的最大價值,加上第i個物品的價值val[i-1],
這就是裝第i個物品的前提下,揹包可以裝的最大價值。
給你乙個可裝載重量為w的揹包和n個物品,每個物品有重量和價值兩個屬性。
其中第i個物品的重量為wt[i],價值為val[i],現在讓你用這個揹包裝物品,最多能裝的價值是多少?
舉個簡單的例子,輸入如下:
n = 3, w = 4
wt = [2, 1, 3]
val = [4, 2, 3]
演算法返回 6,選擇前兩件物品裝進揹包,總重量 3 小於w,可以獲得最大價值 6。
# 0-1揹包問題
import sys
wt =[2
,1,3
]val =[4
,2,3
]n =
3w =
4# dp[i][j]表示,對於前i個物品,當前揹包的容量為j時,揹包可以裝的最大價值,
# 為w+1而不是w表示揹包容量從0開始
dp =[[
0for _ in
range
(w+1)]
for _ in
range
(n+1)]
for i in
range(1
, n+1)
:for j in
range(1
, w+1)
:# 當揹包容量裝不下時,只能選擇不裝,所以和之前大小一樣
if j - wt[i-1]
<0:
dp[i]
[j]= dp[i-1]
[j]else
:# 選擇不裝入揹包和裝入揹包,看哪個更優
# 剩餘重量w-wt[i-1]限制下能裝的最大價值,加上第i個物品的價值val[i-1],
dp[i]
[j]=
max(dp[i-1]
[j], dp[i-1]
[j - wt[i -1]
]+ val[i-1]
)print
(dp[-1
][-1
])
import sys
# 重量
wt =[2
,1,3
]# 價值
val =[4
,2,3
]# 物品個數為n
n =3
# 揹包容量為w
w =4
# dp[i][j]表示,對於前i個物品,當前揹包的容量為j時,揹包可以裝的最大價值,
# 為w+1而不是w表示揹包容量從0開始
dp =[0
for _ in
range
(w+1)]
for i in
range
(n):
for j in
range
(w, wt[i]-1
,-1)
: dp[j]
=max
(dp[j]
, dp[j - wt[i]
]+ val[i]
)print
(dp[-1
])
給定乙個只包含正整數的非空陣列。是否可以將這個陣列分割成兩個子集,使得兩個子集的元素和相等。
注意:每個陣列中的元素不會超過 100
陣列的大小不會超過 200
示例 1:
輸入: [1, 5, 11, 5]
輸出: true
解釋: 陣列可以分割成 [1, 5, 5] 和 [11].
示例 2:
輸入: [1, 2, 3, 5]
輸出: false
解釋: 陣列不能分割成兩個元素和相等的子集.
class
solution
:def
canpartition
(self, nums: list[
int])-
>
bool
: n =
len(nums)
w =sum(nums)
if w%2==
1:return
false
w //=
2# dp[i][j]表示 在載重量為j的情況下,如果前i個元素能夠將揹包放滿,
# 則dp[i][j] = true,如果不能夠放滿,則dp[i][j] = false。
dp =[[
false]*
(w +1)
for _ in
range
(n +1)
]# 初始化base case :dp[...][0] = true,相當於當載重量為0的時候,
# 肯定什麼東西也不用放,揹包肯定預設是滿的,因為載重量為0嘛,所以是true;
# dp[0][...] = false,相當於在任一載重量時,什麼東西都不放,那肯定揹包沒有滿,所以是false
for i in
range
(n+1):
dp[i][0
]=true
nums =[0
]+ nums
for i in
range(1
, n+1)
:for j in
range(1
, w+1)
:if nums[i]
<= j:
dp[i]
[j]= dp[i-1]
[j]or dp[i-1]
[j-nums[i]
]else
: dp[i]
[j]= dp[i-1]
[j]return dp[-1
][-1
]
0 1揹包問題 416 分割等和子集
1 狀態 揹包容量 可選擇的物品 2 選擇 裝或者不裝 3 定義dp陣列 dp i j x,前i個物品,容量為j時的揹包。x為true false 4 初始化 在沒有任何物品裝入時的合法狀態 要求恰好裝滿 dp i 0 只有容量為0的揹包才能滿足 沒有要求恰好裝滿 dp 0 i 即沒有任何物品放入 ...
416 分割等和子集
給定乙個只包含正整數的非空陣列。是否可以將這個陣列分割成兩個子集,使得兩個子集的元素和相等。注意 每個陣列中的元素不會超過 100 陣列的大小不會超過 200 示例 1 輸入 1,5,11,5 輸出 true 解釋 陣列可以分割成 1,5,5 和 11 示例 2 輸入 1,2,3,5 輸出 fals...
416 分割等和子集
主要題目中說了不超過100個數字,數字都不超過200。所以可能的和不會超過20000,這個量級對計算機來說不算大,所以考慮用dp考察每個可能的和是否存在。class solution int sum accumulate nums.begin nums.end 0 if sum 1 int siz ...