您的位置:首页 > 其它

背包问题小结

2015-01-14 17:20 155 查看
我目前接触到背包分为4类,我将逐类介绍

1求背包能装物品价值的最大值

这类问题的模型是 存在一个 容量(重量方面 不考虑体积)为M的背包 现在有n个物品 他们的质量为M[i] 价值为V[i],求能装的物品的最大总价值

这个是 一个典型的动态规划的题目 对于容积进行动态规划,定义F[i] 为容积为i下的能容纳的最大总价值

那么如果在多一个物品k的时候存在这样的关系 F[I] = MAX(F[I- M[K]] + V[k],F(I))

这里其实为了节省空间把二维数组压缩到了线性,更直白的可以定义F[I]
表示在容积I下 前N个物品能存放的最大总价值

数组压缩到了线性也对程序带了限制 动态式中的 F[I-M[K]]对应着二维F(I-M[K])(K-1) 而 F[I]对应着F[I][K]

所以为了保持等式成立 必须从大端向着小端规划

用我自定义的伪代码表示

for 1:n //物品个数

input(m,V) //输入物品质量和价值

for i=M:m //物品只可能影响不小于自身质量的方案

F[I] = MAX(F[I- M[K]] + V[k],F(I))

案例可以参考我之前的博客acm39开心的小明

2完全最大值背包问题

问题模型是 存在一个容量为M的背包,现在有n个物品 他们的质量为M[i] 价值为V[i], 每种物品的数量不限,求能装满背包的方案所能有的最大价值 ,如果不能则输出NO

完全背包因为需要考虑最大值的问题,随意可以用到之前的动态分析基本式

但是在实现需要做个改变

for 1:n //物品个数

input(m,V) //输入物品质量和价值

for i=m:M //物品只可能影响不小于自身质量的方案

F[I] = MAX(F[I- M[K]] + V[k],F(I))

要点一

这道题和之前的最大值为存在一个区别就是 动态规划的时候是从高到低和还是从低到高

最大值问题采用从高到低的策略 因为这样可以避免物品重复的问题,添加一个物品他所考虑的情况都是不包含本身的情况

本体采用从低到高是因为物品可以重复,当考虑物品k时 如果添加一个物品k 能获得空间i+m[k]下的最佳方案,那么在考虑空间i+m[k]的时候 方案里可以包含了至少一个物品K

要点二

F[i]数组初始化的时候要赋值一个负值,但是第0位应该赋值为0,这个负值的大小是有测试数据决定的。

至于这样做的原因是要保证数组能够填满,那这是为什么?因为如果我们全部初始为0,那么我们考虑这种情况,

测试数据:

1

1 50

49 1

最后结果是1 这肯定是不对的

我们回到之前动态规划的基础,我们只考虑了要让得到的价值最大,但是我们却没有考虑背包是否被完全装满,

那么我们此时需要考虑装不满是什么情况:留出的空间是小于输入的重量数据最小的数

换句话说 这样的情况在于 我们最后得到的最大情况是基于f(i) 0<i<min(物品重量) 的情况得到

案例可以参考我之前的博文acm311

3求能装满背包的方案数

问题模型是 存在一个容量为M的背包,现在有n个物品 他们的质量为M[i] ,求能恰好装满背包的方案总数

这个是我之前研究完全背包问题的时候看到的,这里做点总结

这个也是一个动态规划的问题,定义一个F[I]
表示前n项中能恰好填满空间i的方案数

那么就有如果增加一个物品K

那么F[I][K] = F[I][K-1] M[K] >I

F[I][K-1]+F[I-M[K]][K-1] M[K]<=I

参照定义不难理解

伪代码我就不写了

4求能装满背包的方案数变体

问题模型是 存在一个容量为M的背包,现在有n个物品 他们的质量为M[i] ,物品无限使用 求能恰好装满背包的方案总数

这个针对上一个区别在于物品无限使用 函数定义参照之前

那么F[I][K] = F[I][K-1] M[K] >I

F[I][K-1]+(∑ (F[I - k*j][k-1])) M[K]<=I

这个只不过需要多考虑一次添加多个同样物品的情况

3和4都能把空间压缩到线性,和问题1,2是一个原理

另外附上背包问题3,4参考的来源http://blog.csdn.net/wumuzi520/article/details/7021210
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: