0-1背包问题 ACWings题目链接:https://www.acwing.com/problem/content/2/
不会的小伙伴可以看一下视频:https://www.bilibili.com/video/BV15B4y1P7X7/
Python实现
# N件物品,一个容量为V的背包
N,V = map(int,input().split())
weight = []
val = []
# 创建两个列表,分别装入第i个物品的体积wi和价值vi
for _ in range(N):
wi,vi = map(int,input().split())
weight.append(wi)
val.append(vi)
# base case: dp[0][...] = dp[...][0]=0
dp = [[0]*(V+1) for _ in range(N+1)] # (N+1)*(V+1)
# dp[i][w]代表对于前i个物品,当背包容量为w时,可以装的最大价值
for i in range(1,N+1):
for w in range(1,V+1):
"""
if w-weight[i-1]<0:
dp[i][w] = dp[i-1][w]
else:
dp[i][w] = max(
# 装入物品i(下标对应在wight和val中是i-1),剩余的容量是 w-weight[i-1],
# 则dp[i-1][w-weight[i-1]]对应的意思是,前i-1个物品,当背包容量抛去物品i之后可以装的最大价值
dp[i-1][w-weight[i-1]]+val[i-1],
# 不装入物品i,
dp[i-1][w])
"""
# 简化版本
dp[i][w] = dp[i-1][w]
if w-weight[i-1]>=0:
dp[i][w] = max(dp[i][w], dp[i-1][w-weight[i-1]]+val[i-1])
print(dp[N][V])
完全背包问题:(与01背包的区别在于完全背包中每种物品可以无限使用)
ACWings题目链接:https://www.acwing.com/problem/content/3/
很好的题解:https://www.acwing.com/solution/content/5345/
N,V = map(int,input().split())
weight = []
val = []
for _ in range(N):
wi,vi = map(int,input().split())
weight.append(wi)
val.append(vi)
# dp[i][j]代表使用前i个物品,针对容量j的最大价值
# dp[0][...] 为0, dp[...][0]为0
dp = [[0]*(V+1) for _ in range(N+1)]
"""
超时做法:
for i in range(1,N+1):
for j in range(1,V+1):
for k in range(j//weight[i-1]+1):
dp[i][j] = max(dp[i][j], dp[i-1][j-k*weight[i-1]]+k*val[i-1])
"""
for i in range(1,N+1):
for j in range(1,V+1):
dp[i][j] = dp[i-1][j]
if j>=weight[i-1]:
dp[i][j] = max(dp[i][j], dp[i][j-weight[i-1]]+val[i-1])
# print(dp)
print(max(dp[N]))
其实0-1背包和完全背包的代码只有一句不同(注意dp):
0-1背包:
dp[i][w] = dp[i-1][w]
if w-weight[i-1]>=0:
dp[i][w] = max(dp[i][w], dp[i-1][w-weight[i-1]]+val[i-1])
完全背包:
dp[i][j] = dp[i-1][j]
if j>=weight[i-1]:
dp[i][j] = max(dp[i][j], dp[i][j-weight[i-1]]+val[i-1])