1 问题描述
给定一个容量为V的背包和N种物品,每种物品有无限个可用,第i件物品的重量是c[i],收益是w[i],
求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大
2 贪心策略预处理
首先需要对可以放进背包的物品进行一个预处理.根据贪心策略,对于两件物品i和j,如果c[i]>c[j]且w[i]<w[j],直接把物品i舍去,这样才符合物美价廉的思维.想要达到这样的目的,需要对所有物品进行这样的处理:
1. 安排一个数组,数组的每个下标对应的是对应重量的物品,每遍历到相同重量物品时,与数组中该位置的值进行比较,只选取较大的值,遍历完成后,数组保存的即为每个重量下的最大价值.
2. 处理完相同重量的,接下来处理不相同重量的物品.第一步中已经将每个重量的最大价值记录下来了,那么就按照下标从小到大遍历这些数据,每遍历一个数据,就记录下来.如果遍历到的值小于或等于该记录值,说明该物品用了更大的重量获取了更小或者相当的价值,不予理睬.如果遍历到的数据大于记录的值,说明该物品用更大的重量获得了更大的价值,将其加入到哈希表中,并更新记录的值.
代码
1 | /** |
测试数据
|角标|1| 2 |3|4|5|
|——-|——|——–|
|c | 3| 4 |5|3|6|
|w | 4| 5 |6|3|5|
3 方法一:常规思路
从背包问题一的思路延伸过来,问题一中需要考虑的是第i件物品要不要放入背包中,所以需要比较的是放入和不放入两种结果的值.即
max{f[i-1,v],f[i-1,v-c[i]]+w[i]}
设对于第i个物品,放入的次数是k,则上式相当于取k=0
和k=1
两种情况.那么考虑变量k
的话,表达式为
max{f[i-1,v-kc[i]]+kw[i]}
将k的范围考虑进去,即0≤kc[i]≤v
有
f[i,v] = max{f[i-1, v-kc[i]]+kw[i]|0≤kc[i]≤v}
代码
1 | /** |
测试数据
|角标|1| 2 |3|4|5|
|——-|——|——–|
|c | 3| 4 |5|3|6|
| w | 4 | 5 | 6 | 3 | 5 |
4 方法二:转换成01背包问题
01背包问题的最基本思路就是对每个物品只进行0或1的考虑,即放或者不放.完全背包问题中每个物品可以放多次,次数上限为v/c[i]
件.因此可以将一件物品放k次的过程 转换为 k个完全相同的物品放入背包,这样就转换成了01背包问题.所以转换方法就是将一件物品复制成v/c[i]
个完全相同的物品,分别对这些物品进行0或1的决策.
1 | /** |
所得结果与常规方法一样.
5 方法三:进一步优化
在求解01背包问题的一维数组解法时,有注意到,当内循环是正序时就会发生重复添加第i个物品的情况.
1 | /** |