背包问题1(01背包)

背包问题(01背包)

以下内容为学习过程的总结,可能有些copy网上内容,请不要在意这些细节!!

01问题的提出:有N件物品和一个容量为V的的背包,N件物品的费用为c[i](i=1--N);

价值为w[i],问将那些物品放入背包使得价值最大且不超过容量?

思路:

01背包的特点是每种物品只有一件,可以选择放或不放,可以用子问题来定义状态,即

f[ i ][ v ]表示第i件物品放入容量为V的背包中可获得最大的价值,则其状态方程可以表示为

f[ i ][ v ]=max(f[i-1], f[i-1][v-c[i]+w[i]);

这个方程就是01背包的全部内容,将前i件物品放入容量为v的背包中”这个子问题,若只考虑第i件物品的策略(放或不放),那么就可以转化为一个只牵扯前i-1件物品的问题。如果不放第i件物品,那么问题就转化为“前i-1件物品放入容量为v的背包中”,价值为f[i-1][v];如果放第i件物品,那么问题就转化为“前i-1件物品放入剩下的容量为v-c[i]的背包中”,此时能获得的最大价值就是f[i-1][v-c[i]]再加上通过放入第i件物品获得的价值w[i]。

优化方法:

上面的方程式是用二维数组,想想是否可以用一维数组解决问题,所以就有了优化方法

代码如下:

for i=1..N
    for v=V..0
        f[v]=max{f[v],f[v-c[i]]+w[i]};

对于上面的优化方法是这样的,思路是要求出f[i][v]需要用到肯定是有一个主循环i=1..N,每次算出来二维数组f[i][0..V]的所有值。那么,如果只用一个数组f[0..V],能不能保证第i次循环结束后f[v]中表示的就是我们定义的状态f[i][v]呢?

f[i][v]是由f[i-1][v]和f[i-1][v-c[i]]两个子问题递推而来,能否保证在推f[i][v]时

(也即在第i次主循环中推f[v]时)能够得到f[i-1][v]和f[i-1][v-c[i]]的值呢?

事实上,这要求在每次主循环中我们以v=V..0的顺序推f[v],这样才能保证推f[v]时f[v-c[i]]保存的是状态f[i-1][v-c[i]]的值。

初始化细节:

对于01背包的问题一般有两种问题,

一是问将背包装满时的最优解;

二是背包不装满时的最优解;

对于以上两种的数组初始化是不一样的,第一组要求背包恰好装满着初始化要求f[0]=0;

f[1--n]=-∞  ;

对于第二种这要求全部初始化为0;

初始化的f数组事实上就是在没有任何物品可以放入背包时的合法状态。如果要求背包恰好装满,那么此时只有容量为0的背包可能被价值为0的nothing“恰好装满”,其它容量的背包均没有合法的解,属于未定义的状态,它们的值就都应该是-∞了。如果背包并非必须被装满,那么任何容量的背包都有一个合法解“什么都不装”,这个解的价值为0,所以初始时状态的值也就全部为0了。

补充内容:

01背包是最为基本的背包类型,所以对01背包的变形会有很多种,所以就需要你深刻理解01背包的思想和实现步骤,这几天做题发现了一个变形,以后看到背的变形还会补充;

该题是hdu2955

http://acm.hdu.edu.cn/showproblem.php?pid=2955

这题是一道典型的01背包,但所不同的是需要你用01背包的思想转化问题,题意是一个劫匪想去抢银行,给你一个被抓的概率和几个银行和在这个银行被抓的概率,一看题这不是把概率当背包,套公式就完了,可是你想过概率怎么加吗?

所以这题做法不是将概率作为背包,而是抢的钱作为背包,计算出所有的钱的集合,然后递减求的抢这些钱的概率,然后与你被抓的概率做比较,输出大于该概率的系数,也就是你能抢的钱数,这个变形很有意思,当然会对你对01背包理解更加深刻,做做吧!

代码这里就不给出了,网上别人的博客有,不会可以看看!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值