算法:零一背包

零一背包问题是一个动态规划的经典实例,用于求解背包容量限制下物品最大价值。文章介绍了例题HDU2602 Bone Collector,详细阐述了状态、转移方程、初值设定以及答案。通过二维数组表示状态,并讨论了如何优化空间,采用倒序循环避免后效性。算法的时间复杂度为O(n * m)。

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

零一背包问题是一个非常重要的动态规划求解的问题,只要你学习DP就不可不学零一背包,所以务必要认真学习这个问题。

例题

hdu2602 Bone Collector

题目描述:
"骨头收集者"带着体积V的背包去捡骨头,已知每个骨头的体积和价值,求能装进背包的最大价值。N <= 1000, V <= 1000。

输入格式:
第一行:是测试数据。
接下来对于每组测试数据,第一行是骨头数量和背包体积,第二行是每个骨头的价值,第三行是每个骨头的体积。

输出格式:
一个整数,为最大价值总和是多少。

输入样例:

1
5 10
1 2 3 4 5
5 4 3 2 1

输出样例:

14

零一背包

看到这道题,想想暴力、贪心貌似都不行,那么此时就要来dp了。而提到DP,就一定就要去想:状态、转移方程、初值和答案了。

  1. 状态:dp[i] [j]指到第i个物品,重量为j时,价值总和的最大值。
  2. 转移方程:dp[i] [j] = max(dp[i - 1] [j], dp[i - 1] [j - w[i]] + v[i])
    其实这个的意思就是:分两种情况讨论,如果说不选这第i个物品,那么直接把dp[i] [j] = dp[i - 1] [j]就行了,但是如果说选这个物品,那么就得分析一下了,先看重量:要找dp[i] [j],就必然是由dp[i] [j - w[i]]推过来的,而不是dp[i] [j + w[i]]为什么呢?不妨设dp[i] [j]是由dp[i] [x]推过来的,上一个重量x是加上了一个w[i]才得到现在的重量j的值的,所以说x + w[i] = j,根据等式的性质2,得出x = j - w[i]。接下来就比较简单了,价值让dp[i] [j - w[i]] + v[i]就好了。最后,因为要取价值的最大值,就让两种情况取个max就没问题了。
  3. 初值:dp[i] [j] = 0;
  4. 答案:dp[n] [m],考虑到最后一个数得出的答案,一定是分析完所有的数了,所以必然是最大值。

这是按照题目中所述样例制作而成的表格(第j行第i列表示dp[i] [j]的大小可以借鉴)。
在这里插入图片描述
但是二维动态规划消耗的内存太大了,我们想去优化空间,那么我们当然会想到直接将二维数组降成一维数组了。可如果直接改我们会发现这样不对的,为什么呢?

因为,dp[j]先

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值