题目:
背包重量w,n件物品,weight[i]和value[i],找到最大值。
1.dp
dp[i][j] 表示在(0,i)中任选几件放到重量为j的背包中,所能获得的最大价值。
2. 状态转移
有两种情况,一种是放一种是不放。
不放是因为,这个时候的j比weight[i]要小,那么就肯定是放不下i的,所以dp[i][j] = dp[i-1][j]
放是因为,这个时候的j比weight[i]要大,那这个时候我们就要看,当j减去weight[i],表示有空间放入j的时候,(0,i-1)中的最大dp。即 dp[i-1][j-weight[i]]。这个时候我们要考虑,dp[i][j]是放入i大,还是不放入i大,那么我们就需要比较dp[i-1][j]和dp[i-1][j-weight[i]],即dp[i][j] = max(dp[i-1][j],dp[i-1][j-weight[i]])
3. 初始化
dp[i][j]是由dp[i-1]推导来的,那么我们就需要考虑,i=0的情况。分为两种,如果j<weight[0],那么说明装不下物品0,所以dp[0][j] = 0. 如果j>=weight[0],那么说明装得下物品0,所以dp[0][j] = value[0].
还要考虑j=0的情况,那么显然,j=0时,无法装物品,所有的dp[i][0]均为0.
4. 遍历顺序
先物品再背包
for i in range(1,n):
for j in range(1,w+1):
if j < weight[i]:
dp[i][j] = dp[i-1][j]
else:
dp[i][j] = max(dp[i-1][j],dp[i-1][j-weight[i]]+value[i])
5 举例
w = 4
weight = [1,3,4]
value = [15,20,30]
求dp[2][4]=35
代码如下:
w = 4
weight = [1,3,4]
value = [15,20,30]
def package_01(w:int, weight:list[int], value:list[int]) -> int:
n = len(weight)
# 初始化
dp=[[0]*(w + 1) for _ in range(n)]
for i in range(n):
dp[i][0] = 0
for j in range(w+1):
if j < weight[0]:
dp[0][j] = 0
else:
dp[0][j] = value[0]
# 状态转移
for i in range(1,n):
for j in range(1,w+1):
if j < weight[i]:
dp[i][j] = dp[i-1][j]
else:
dp[i][j] = max(dp[i-1][j],dp[i-1][j-weight[i]]+value[i])
return(dp[n-1][w])
print(package_01(w,weight,value))