0-1背包问题详解

来源:互联网 发布:淘宝网一件代发赚钱吗 编辑:程序博客网 时间:2024/06/03 13:37

0/1背包问题:有n件物品,每件物品i的重量为w[i],价值为v[i];有一个背包,最大承重量为c。要求向包中放入若干件物品,使的物品总重不超过背包承重量,且包中物品的总价值最大。

 

0-1背包问题可以用回溯法、搜索解空间法、动态规划法等。其中动态规划方法思想和实现都较为简单,时间复杂度也较低,因而比较常用。网上很多c或者c++的动态规划实现0-1背包的代码都是错误的。这里对该问题给出较为详细的解释,并给出亲测的版本。

动态规划问题实现0-1背包问题关键在状态的构造,也就是子问题的构造——定义f[i][j],含义为在容量为 j 时,考虑前 i 件物品所能得到的最大价值是多少。为什么这样定义状态,是要仔细斟酌的。f[i][j]可以根据前一个状态推得——对于第 i 件物品,只有两个状态,取或者不取。如果不取,则可以获得的最大价值寄希望于前i-1件物品就可以了:即f[i][j] = f[i-1][j];如果取第i 件物品,则留给前i-1件物品的最大承重量就小了,即减去第i件物品的重量,当然总价值中分为第i件物品的价值和前i-1件的最大价值,f[i][j] = f[i-1][j - w[i]] + v[i]。

可以这样理解,初值比较好算:f[i][0]和f[0][j]的值全部为0;f[1][j]表示:在包的容量为j = [0, c]时,可以获得的最大价值;f[2][j]表示:在包的容量为j = [0, c]时,可以获得的最大价值;这时候考虑,f[2][j]是怎么得来的?是根据f[1][j] 和 f[1][j - w[1]] + v[1] 得到的,而w[1]值是多少不确定,所以可以理解为什么要这么表示状态了吧。

 

下面有个简单的例子,走一边此例,会更加明白动态规划的运行机理:

测试数据:有3件物品,最大承重为10;

w[3] = {3,4,5};  
v[3] = {4,5,6};

这里值得注意的是,f[i][j] = f[i-1][j - w[i]] + v[i] 式中,编程时w[i]和v[i]替换为w[i-1]和v[i-1]。


0 0
原创粉丝点击