01背包与完全背包-python

背包问题

初始值

物品重量 w = [3, 4, 5, 7]
物品价值 v = [1, 5, 6, 9]
物品数量 n = 4
背包容量 c = 10

01背包

ans = 11

递归求解

递归思路
背包容量剩余 cnt 的情况下, 在第 i 个及以后物品里装最大价值的东西

def backbag(i, cnt):
    if i == n or cnt == 0: # 没有物品可供选择或者背包容量为0, 能装的东西的价值为 0
        return 0
    if w[i] <= cnt: # 当前物品的重量低于背包容量, 可以考虑装还是不装 
        yes = backbag(i+1, cnt - w[i]) + v[i]   # 将第 i 号物品装入背包
        no = backbag(i + 1, cnt)  # 不装入第 i 号物品
        return max(yes, no) # 取其中的较大值
    else: # 无法装入,继续选择后面的物品
        return backbag(i + 1, cnt)
print(backbag(0, c)) # 初始从第一个物品开始选择, 背包容量为 c

输出结果为 11

动态规划求解

w.insert(0, 0)
v.insert(0, 0) # 让行标与物品索引能一一对应
dp = [[0] * (c + 1) for i in range(n + 1)]
for i in range(1,n+1):
    for j in range(c + 1):
        if w[i] <= j: # 可以放入, 比较放入此物品与不放入此物品的最大价值,去较大值
            dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - w[i]] + v[i])
        else: # 不能放入, 则继承值
            dp[i][j] = dp[i - 1][j]
print(dp[-1][-1]) # 输出结果

完全背包

递归解法

递归思路:如果能装入, 则将其装入,并且是在当前行的基础上处理
递归解法很好用, 但是难理解一些

w = [3, 4, 5, 7]
v = [1, 5, 6, 9]
n = 4
c = 10
def fun(i, cnt):
    if i == n or cnt == 0:
        return 0 
    if cnt >= w[i]:
        return max(fun(i + 1, cnt), fun(i, cnt - w[i]) + v[i]) 
        # 不装入此物品 与 在当前物品的情况下, 继续装入此物品的较大的值
    else:
        return fun(i + 1, cnt) # 无法装入, 进入下一个物品的递归
print(fun(0, c)) # 最后返回的是一个数。

动态规划求解

w.insert(0, 0)
v.insert(0, 0) # 让行标与物品索引能一一对应
dp = [[0] * (c + 1) for i in range(n + 1)]
for i in range(1,n+1):
    for j in range(c + 1):
        if w[i] <= j: # 可以放入, 在左侧与上方结果中选择最大值
            dp[i][j] = max(dp[i - 1][j], dp[i][j - w[i]] + v[i]) 
        else: # 不能放入, 则继承值
            dp[i][j] = dp[i - 1][j]
print(dp[-1][-1])

01背包与完全背包动态规划的唯一区别: 在上一行的基础上推导 vs 在当前行基础上推导

多重背包问题

多重背包的问题, 可以转化为01背包问题来求解

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值