[算法][动态规划][背包问题①]0-1背包问题的优化及约束变形[python实现]

这篇博客介绍了0-1背包问题的动态规划解决方案,包括动态过程、代码实现、算法优化和约束变形。通过空间优化和算法加速,降低了复杂度。文章还讨论了如何处理恰好放满背包的约束条件,并提供了完整的Python代码测试。
摘要由CSDN通过智能技术生成


写在前面

如果无法访问码云的代码库,请访问此处本文源码@Gist


题目描述

有一个重量上限容量为 t o t a l total total 的背包和 i t e m _ n u m item\_num item_num 种物品,第 i i i 种物品的重量是 w i w_i wi 、价值为 v i v_i vi ,求问选择将哪些物品放入背包(每种物品的数量有且只有一件)可以得到最大的价值。

问题求解

1.1 动态过程

动态规划的精髓在于拆解大问题为子问题。我们给定一种数据结构dp[item_num][total],其中,dp[i][j]表示第i+1次尝试把物品i放入背包后,背包剩余容量为j,此时背包中的物品总价值为dp[i][j]

Tip:物品的序数从0计起,放入背包的动作过程从第1次计起。

由于每次尝试把物品放入背包的过程是一个动态过程,其动态转移方程为:
d p [ i + 1 ] [ j ] = m a x { d p [ i ] [ j − w i ] + v i , d p [ i ] [ j ] } dp[i+1][j]=max\{dp[i][j-w_i]+v_i,dp[i][j]\} dp[i+1][j]=max{ dp[i][jwi]+vi,dp[i][j]}显然i是主要的状态转移量:

for i in range(item_num):  # 第i+1次尝试放入第i个物品(物品序号从0起||显然,尝试次数从1起,即i+1)
    # 以下是动态转移过程
    for j in range(total, -1, -1):  # 倒序遍历背包剩余容量,即 for(inr j = total; j>=0; j--)
        dp[i+1][j] = max(dp[i][j-w[i]]+v[i],dp[i][j]) if j >= w[i] else dp[i][j]
        # 等价于:
        # if j >= w[i] and dp[i][j-w[i]] + v[i] > dp[i][j]:  # 第[i+1]次尝试放入时选择放入第[i]个物品
        #     dp[i+1][j] = dp[i][j-w[i]] + v[i]  # 更新第i+1次尝试放入的推测值(物品总价值)
        # else:  # 跳过物品,不考虑放入该物品,拷贝"前[i]次尝试放入"的堆栈数据到[i+1]上
        #     dp[i+1][j] = dp[i][j]

即,第i+1次考虑要不要把第i个物品放入背包(0-1问题中恰好 n n n个物品最多只考虑 n n n次"放不放"的问题),知道它的重量 w i w_i wi 和价值 v i v_i vi,当dp[i][j-w[i]] + v[i] > dp[i][j],即前一次(dp[i][~])考虑时,没有放入 w i w_i wi重量的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值