背包问题
先循环物品
再循环体积
最后循环策略(选或不选、选一件两件三件…s件)
2. 01背包问题
2. 01背包问题
01背包二维实现的转移方程
dp[i][j]表示只考虑前i件物品,体积小于等于j时,最大的价值(全部初始化为0)
dp[i][j] = max(dp[i-1][j],dp[i-1][j-vi]+wi)
因为只依赖上一行的结果,因此可以优化为2*(v+1)
dp[i%2][j] = max(dp[(i-1)%2][j],dp[(i-1)%2][j-vi]+wi)
因为只依赖上一行及左边的结果,因此可以进一步优化为一维
内层体积循环倒序
n,v = map(int,input().split())
dp = [0 for _ in range(v+1)]
for _ in range(n):
c,w = map(int,input().split())
for j in range(v,c-1,-1):
dp[j] = max(dp[j],dp[j-c]+w)
print(dp[-1])
3. 完全背包问题
n,v = map(int,input().split())
dp = [0 for _ in range(v+1)]
for _ in range(n):
v1,w1 = map(int,input().split())
for j in range(v1,v+1):
dp[j] = max(dp[j],dp[j-v1]+w1)
print(dp[-1])
4. 多重背包问题 I
4. 多重背包问题 I
物品可以选0件1件…s件
n,v = map(int,input().split())
dp = [0 for _ in range(v+1)]
for _ in range(n):
v1,w1,s1 = map(int,input().split())
for j in range(v,v1-1,-1):
for s in range(1,s1+1):
if j>=s*v1:
dp[j] = max(dp[j],dp[j-s*v1]+s*w1)
print(dp[-1])
5. 多重背包问题 II
5. 多重背包问题 II
多重背包的二进制优化方法
例:0-7可以由1 2 4三个数表示出来
0-10可以由1 2 4 3四个数表示出来
n,v = map(int,input().split())
dp = [0 for _ in range(v+1)]
for _ in range(n):
v1,w1,s1 = map(int,input().split())
goods = []
k = 1
while k<s1:
s1 -= k
goods.append((k*v1,k*w1))
k*=2
if s1>0:
goods.append((s1*v1,s1*w1))
for good in goods:
for j in range(v,good[0]-1,-1):
dp[j] = max(dp[j],dp[j-good[0]]+good[1])
print(dp[-1])
6. 多重背包问题 III
6. 多重背包问题 III
多重背包的单调队列优化方法。
TODO
7.混合背包问题
n,v = map(int,input().split())
dp = [0 for _ in range(v+1)]
for _ in range(n):
goods = []
c,w,s = map(int,input().split())
if s==-1 or s==0:
goods.append((c,w,s))
else:
k = 1 #二进制的分解
while k<=s:
s -= k
goods.append((c*k,w*k,-1))
k*=2
if s>0:
goods.append((c*s,w*s,-1))
for good in goods:
if good[-1]==0:
for j in range(good[0],v+1):
dp[j] = max(dp[j],dp[j-good[0]]+good[1])
else:
for j in range(v,good[0]-1,-1):
dp[j] = max(dp[j],dp[j-good[0]]+good[1])
print(dp[-1])
8. 二维费用的背包问题
n,v,m = map(int,input().split())
dp = [[0 for _ in range(m+1)] for _ in range(v+1)] #二维数组
for _ in range(n):
v1,m1,w1 = map(int,input().split())
for j in range(v,v1-1,-1):
for k in range(m,m1-1,-1):
dp[j][k] = max(dp[j][k],dp[j-v1][k-m1]+w1)
print(dp[-1][-1])
9. 分组背包问题
9. 分组背包问题
分组背包问题:多重背包问题中的s件看作是s组,每组只能选一个
n,v = map(int,input().split())
dp = [0 for _ in range(v+1)]
for _ in range(n):
s = int(input())
v1 = []
w1 = []
for _ in range(s):
a,b = map(int,input().split())
v1.append(a)
w1.append(b)
for j in range(v,0,-1):
for k in range(0,s):
if j>=v1[k]:
dp[j] = max(dp[j],dp[j-v1[k]]+w1[k]) ##与多重背包问题的区别
print(dp[-1])
10. 有依赖的背包问题
TODO
学习资源来自大雪菜大佬的背包九讲专题https://www.bilibili.com/video/BV1qt411Z7nE