1. 0/1背包
dp = [0 for i in range(m+1)]
for i in range(1,n+1):
for j in range(m,w[i]-1,-1):
dp[j] = max(dp[j],dp[j-w[i]]+v[i])
2. 完全背包
dp = [0 for i in range(m+1)]
for i in range(1,n+1):
for j in range(w[i],m+1):
dp[j] = max(dp[j],dp[j-w[i]]+v[i])
3. 多重背包(二进制优化)
W = [None]
V = [None]
for i in range(1,n+1):
w,v,num = map(int,input().strip().split())
k = 1
while k <= num:
num = num - k
W.append(k*w)
V.append(k*v)
k = k*2
if num > 0:
W.append(num*w)
V.append(num*v)
dp = [0 for i in range(m+1)]
for i in range(1,len(W)):
for j in range(m,W[i]-1,-1):
dp[j] = max(dp[j],dp[j-W[i]]+V[i])
4. 一维费用背包(求最小值) 拿到价值m的最小重量
dp = [inf for i in range(m+1)]
dp[0] = 0
for i in range(1,n+1):
for j in range(m,0,-1):
if j < v[i]:
dp[j] = min(dp[j],w[i])
else:
dp[j] = min(dp[j],dp[j-v[i]]+w[i])
5. 二维费用背包
V = [None for i in range(n+1)]
M = [None for i in range(n+1)]
W = [None for i in range(n+1)]
for i in range(1,n+1):
V[i],M[i],W[i] = map(int,input().strip().split())
dp = [[0 for j in range(m+1)] for i in range(v+1)]
for k in range(1,n+1):
for i in range(v,V[k]-1,-1):
for j in range(m,M[k]-1,-1):
dp[i][j] = max(dp[i][j],dp[i-V[k]][j-M[k]]+W[k])
print(dp[v][m])
6. 背包计数,在背包容量为m时,拿到最大价值的方案数 ★★★
def f(n,m):
ans = [1 for j in range(m+1)]
dp = [0 for j in range(m+1)]
for i in range(1,n+1):
w,v = map(int,input().strip().split())
for j in range(m,w-1,-1):
if dp[j] < dp[j-w]+v:
ans[j] = ans[j-w]
elif dp[j] == dp[j-w]+v:
ans[j] = (ans[j]+ans[j-w])%(10**9+7)
dp[j] = max(dp[j],dp[j-w]+v)
print(ans[m])
7. 分组背包 ★
W = [[] for i in range(n+1)]
V = [[] for i in range(n+1)]
num = [0 for i in range(n+1)]
for i in range(1,n+1):
num[i] = int(input().strip())
for j in range(num[i]):
w,v = map(int,input().strip().split())
W[i].append(w)
V[i].append(v)
dp = [0 for j in range(m+1)]
for i in range(1,n+1):
for j in range(m,0,-1):
for k in range(num[i]):
if j >= W[i][k]:
dp[j] = max(dp[j],dp[j-W[i][k]]+V[i][k])
print(dp[m])
8. 混合背包
W = [None]
V = [None]
for i in range(1,n+1):
w,v,num = map(int,input().strip().split())
if num == -1:
num = 1
elif num == 0:
num = m//w
k = 1
while k <= num:
num = num - k
W.append(k*w)
V.append(k*v)
k = k * 2
if num > 0:
W.append(num*w)
V.append(num*v)
dp = [0 for i in range(m+1)]
for i in range(1,len(W)):
for j in range(m,W[i]-1,-1):
dp[j] = max(dp[j],dp[j-W[i]]+V[i])
print(dp[m])
9. 背包问题求具体方案 ★★★
W = [None for i in range(n+1)]
V = [None for i in range(n+1)]
dp = [[0 for j in range(m+1)] for i in range(n+2)]
for i in range(1,n+1):
W[i],V[i] = map(int,input().strip().split())
for i in range(n,0,-1): #注意,此处逆序
for j in range(m,0,-1):
dp[i][j] = dp[i+1][j]
if j >= W[i]:
dp[i][j] = max(dp[i][j],dp[i+1][j-W[i]]+V[i])
now_w = m
for i in range(1,n+1):
if now_w <= 0:
break
if now_w >= W[i] and dp[i][now_w] == dp[i+1][now_w-W[i]]+V[i]:
print(i,end = ' ')
now_w = now_w - W[i]
10. 有依赖的背包 ★★
def dfs(x):
global W,V,dp,m
for j in range(W[x],m+1):
dp[x][j] = V[x]
for i in range(len(son[x])):
y = son[x][i]
dfs(y)
for j in range(m,W[x]-1,-1):
for k in range(j-W[x]+1):
dp[x][j] = max(dp[x][j],dp[x][j-k]+dp[y][k])
def f(n,m):
global son,root,dp
for i in range(1,n+1):
W[i],V[i],f = map(int,input().strip().split())
if f == -1:
root = i
else:
son[f].append(i)
dfs(root)
print(dp[root][m])
if __name__ == '__main__':
n,m = map(int,input().strip().split())
root = None
son = [[] for i in range(n+1)]
W = [None for i in range(n+1)]
V = [None for i in range(n+1)]
dp = [[0 for j in range(m+1)] for i in range(n+1)]
f(n,m)