背包九讲-Python实现

本文深入探讨了背包问题的多种类型,包括01背包、完全背包、多重背包及其优化方法,如二维实现、二进制优化和单调队列优化。通过实例展示了如何解决这些问题,并提供了详细的代码实现。此外,还提及了混合背包问题、二维费用的背包问题和分组背包问题,以及有依赖的背包问题的待解决状态。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

背包问题
先循环物品
再循环体积
最后循环策略(选或不选、选一件两件三件…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. 完全背包问题

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.混合背包问题

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. 二维费用的背包问题

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. 有依赖的背包问题

10. 有依赖的背包问题
在这里插入图片描述
在这里插入图片描述

TODO

学习资源来自大雪菜大佬的背包九讲专题https://www.bilibili.com/video/BV1qt411Z7nE

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值