0-1背包问题
来源:互联网 发布:淘宝店铺宝贝分类代码 编辑:程序博客网 时间:2024/06/05 10:59
0-1背包问题
在N件物品取出若干件放在容量为W的背包里,每件物品的体积为W1,W2……Wn(Wi为整数),与之相对应的价值为P1,P2……Pn(Pi为整数)。求背包能够容纳的最大价值。
输入
第1行,2个整数,N和W中间用空格隔开。N为物品的数量,W为背包的容量。(1 <= N <= 100,1 <= W <= 10000)第2 - N + 1行,每行2个整数,Wi和Pi,分别是物品的体积和物品的价值。(1 <= Wi, Pi <= 10000)
输出
输出可以容纳的最大价值。
输入示例
3 62 53 84 9
输出示例
14
0-1背包问题:第一想法是?(1) 枚举?万能的枚举啊。但对于n件物品,每件都可以选择取或者不取,总的可能性有2n, n = 30就大约已经有10亿种可能了!枚举所有可能选择一种不超过背包承重并且价值最大的物品组合,枚举量太大了。(2) 贪心? 嗯,有点意思。先选最贵重的物品?找个反例:
按照先选贵重物品的策略,会先选择价值为3的那个,并且背包装满了,但是如果我们选取前两个物品,总价值可以达到4。
可能你已经想到了,考虑“性价比”,先选取“性价比”高的。性价比怎么定义呢?用价值除以重量!先选取单位重量价值最大的物品试试?
f(i,j)=⎧⎩⎨⎪⎪⎪⎪⎪⎪⎪⎪0(i=0∩j=0)−∞(i=0∩j>0)f(i−1,j)(i>0∪j<w)max(f(i−1,j),f(i−1,j−wi)+vi)(i>0∪j>wi)
max{f[n][i]} (0<=i<=n) ;
注意这里i可以等于0——如果背包一件物品都容纳不了呢?
至此我们的问题得到了解答。fmax{f[n][i]} (0<=i<=n)
n = 3, m = 3
v = (2,2,3)
w = (1,2,3)
v = (2,2,3)
w = (1,2,3)
按照先选贵重物品的策略,会先选择价值为3的那个,并且背包装满了,但是如果我们选取前两个物品,总价值可以达到4。
可能你已经想到了,考虑“性价比”,先选取“性价比”高的。性价比怎么定义呢?用价值除以重量!先选取单位重量价值最大的物品试试?
(3) 试试动态规划?
我们从1-n一件一件选择物品,为什么要记录之前选择了哪些物品呢? 因为我们要计算重量和价值,那我们能不能只记录重量和价值呢?可以的。
令f(i,j)表示选决定了前i件物品,重量恰好为j的时候能获得的最大价值。
假设我们已经知道了全部的f(i-1,*)的值,如何求f(i,*),换句话说我们有了状态表示还不够,如何求出递推式?
对f(i,j)如果我们不选取第i件物品,则显然f(i, j) = f(i – 1,j)
如果我们要选取第i件物品,那么前i – 1件物品必须要达到j - wi且价值最大。由我们对f的定义,有f(i,j) = f(i-1,j - wi) + vi, 那么我们究竟选不选第i件物品呢?只好看哪个大了值大了,所以由
假设我们已经知道了全部的f(i-1,*)的值,如何求f(i,*),换句话说我们有了状态表示还不够,如何求出递推式?
对f(i,j)如果我们不选取第i件物品,则显然f(i, j) = f(i – 1,j)
如果我们要选取第i件物品,那么前i – 1件物品必须要达到j - wi且价值最大。由我们对f的定义,有f(i,j) = f(i-1,j - wi) + vi, 那么我们究竟选不选第i件物品呢?只好看哪个大了值大了,所以由
f(i,j) = max(f(i – 1, j) , f(i-1,j - wi) + vi);
当然只有j>= wi的时候我们才有选择第i件物品的权力。
那么初值是什么呢?f(0,*),一件物品也不选的时候,显然重量只能是0,其他的重量都不存在,我们用负无穷来表示不可能,因为求的是最大价值嘛。
那么,我们整理一下我们的递推式子和初值:
那么初值是什么呢?f(0,*),一件物品也不选的时候,显然重量只能是0,其他的重量都不存在,我们用负无穷来表示不可能,因为求的是最大价值嘛。
那么,我们整理一下我们的递推式子和初值:
那么我们求的值是什么呢? 回想f的定义,最终的答案是背包要装的物品价值最大。那么答案应该
max{f[n][i]} (0<=i<=n) ;
注意这里i可以等于0——如果背包一件物品都容纳不了呢?
至此我们的问题得到了解答。
f(0) = 0f(1..m) = -∞for i = 1 to n do for j = m downto wi do f(j) = max(f(j), f(j - wi)) endforendfor
所求结果是max{f(0..m)}
注意我们循环j只到wi,因为再小的j会导致我们无法选择第i件物品,这时我们直接使用不用第i件物品的旧值就好啦。简单吧?
那么现在,时间复杂度时不变的,空间复杂度降低O(m)了。尝试换一种状态表示? 我们令f(i,j)表示决定了前i件物品,总重量不超过j时能获得的最大价值。仔细想想递推式是不变的,那么初值呢?如果初值不变,f就没变化了……i= 0时,总重量时0,又因为0不超过任何整数,所以根据定义初值是f(0,*) = 0
那么最终结果呢?根据定义,最终结果是f(n,m)而没有必要再一串数里取最大了。可见即使递推式相同,初值不同也会定义不同的函数,请不要忽略初值的作用啊。同样我们可以优化掉第一维。
那么最终结果呢?根据定义,最终结果是f(n,m)而没有必要再一串数里取最大了。可见即使递推式相同,初值不同也会定义不同的函数,请不要忽略初值的作用啊。同样我们可以优化掉第一维。
核心伪代码:
初值f(0..m) = 0for i = 1 to n do for j = m downto wi do f(j) = max(f(j), f(j - wi)) endforendfor
所求结果是f(m);
AC代码:
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int maxn=10010;int dp[maxn],a[maxn],b[maxn];int main(){int n,m;while(scanf("%d %d",&n,&m)!=EOF){for(int i=1;i<=n;i++){scanf("%d %d",&a[i],&b[i]);}memset(dp,0,sizeof(dp));for(int i=1;i<=n;i++){for(int j=m;j>=a[i];j--){dp[j]=max(dp[j],dp[j-a[i]]+b[i]);}}printf("%d\n",dp[m]);}return 0;}
阅读全文
0 0
- 背包问题(0-1背包、完全背包、多重背包)详解
- 背包问题和0-1背包问题
- 背包问题和0-1背包问题
- 背包问题系列--"0-1背包问题"
- 背包笔记-含0/1背包问题、完全背包问题、多重背包问题、二维背包问题、分组背包问题
- 【背包问题】背包问题之0-1背包、完全背包、多重背包
- 0-1背包问题
- 0/1背包问题
- 0,1背包问题
- 0-1背包问题
- 0/1背包问题
- 0-1背包问题
- // 0-1背包问题
- 0/1背包问题
- 0-1背包问题
- 0-1背包问题
- 0-1背包问题
- 0/1背包问题
- python使用 UTF-8编码
- 机翼的翼型和升力
- 洛谷p2239 螺旋矩阵
- 动态规划
- vue组件中$emit()的作用
- 0-1背包问题
- 链接器
- DOM文档对象模型
- 【PAT】【Advanced Level】1063. Set Similarity (25)
- 为什么不要问我DB极限QPS/TPS
- 测试小故事38:时间不够测不了
- Android屏幕适配
- 【物联网】6LoWPAN技术
- EnumUtil根据值获取枚举对象