您的位置:首页 > 其它

背包整理(1) 01,完全,多重

2014-04-11 12:38 225 查看
背包问题 一

01背包:

一般的题目描述是:有N 件物品和一个容量为V 的背包。放入第i 件物品耗费的费用是Ci,得到的价值是Wi。求解将哪些物品装入背包可使价值总和最大。

这是最基础的背包问题,特点是:每种物品仅有一件,可以选择放或不放。

用子问题定义状态:即 dp[i][v] 表示前 i 件物品恰放入一个容量为 v 的背包可以获得的最大价值。

//dp
[V];注意:输入的起始地址为1;初始化dp,都为0;
for(i=1 ; i<=N ; i++)
for(j= c[i] ; j<=V; j++)//注意是从小到大;
dp[i][j]=max(dp[i-1][j],dp[i-1][j-C[i]]+W[i]);
// 则dp
[V]就是要找的值;


以上方法的时间和空间复杂度均为O(V N),其中时间复杂度应该已经不能再优化了,但空间复杂度却可以优化到O(V)。

for(i=1 ; i<=N ; i++)
for(j= v; j>=c[i]; j--)//注意是从大到小;
dp[j]=max(dp[v],dp[v-C[i]]+W[i]);
// 则dp
[V]就是要找的值;


PS:实际上会有两种情况,一个是恰好装满,dp[0]=0, 其他需要初始化为负无穷;一个只是寻找最优的解决方案,全部初始化为0就行了;

完全背包:

这个问题非常类似于01背包问题,所不同的是每种物品有无限件。也就是从每种物品的角度考虑,与它相关的策略已并非取或不取两种,而是有取0件、取1件、取2件??等很多种。

如果仍然按照解01背包时的思路,令f[i][v]表示前i种物品恰放入一个容量为v的背包的最大权值。

仍然可以按照每种物品不同的策略写出状态转移方程,像这样

f[i][v]=max{f[i-1][v-k*c[i]]+k*w[i] | 0<=k*c[i]<=v}


但是可以转化为01背包来解决为题; 初始化时 dp[V] 都为0; 输入从下标一开始;

for(int i=1 ; i<=n ;i++)
for(int j=c[i]; j<=V; j++)//注意:从小到大;
dp[j]=max(dp[j],dp[j-c[i]]+w[i]);
//最后的结果就为;dp[V];


多重背包:

下面进入关键时刻,完全背包:

另一种好想好写的基本方法是转化为01背包求解:把第i种物品换成n[i]件01背包中的物品,则得到了物品数为Σn[i]的01背包问题,直接求解,复杂度仍然是O(V*Σn[i])。

但是我们期望将它转化为01背包问题之后能够像完全背包一样降低复杂度。

仍然考虑二进制的思想,我们考虑把第i种物品换成若干件物品,使得原问题中第i种物品可取的每种策略——取0..n[i] 件——均能等价于取若干件代换以后的物品。

另外,取超过n[i]件的策略必不能出现。

方法是:将第i种物品分成若干件物品,其中每件物品有一个系数,这件物品的费用和价值均是原来的费用和价值乘以这个系数。使这些系数分别为1,2,4,...,2^(k-1),n[i]-2^k+1,

按照总的价值来分,如果那个商品的数量为1,就按01,背包,如果是多个,就按完全背包,来解答;
看看例题吧: HDU 2844 HUD 1059
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: