背包问题一直是动态规划中的经典问题。这个问题又分成01背包,完全背包,多重背包,分组背包等等。。我在这里只记录下01背包(0-1knapsack)和完全背包(unbounded knapsack)。背包问题的简单描述就是有一个背包和一堆物品。每个物品有自己的大小和价值。我们希望在一个特定容量的背包中放入价值尽可能大的物品。01背包呢就是每个物品最多只能放一次,也就是要么放要么不放,所以被称为01背包。而完全背包呢就是每个物品可以放无限次。我们更喜欢unbounded knapsack这个名字。因为完全这次词其实没有表达清楚不限的意思。下面就是对完全背包和01背包就动态规划的方法做一些解析。
这两个问题中似乎01背包比较爽快,就从爽快的先说。类似的,我们还是要找到一个优化的子结构,然后递归式,然后代码。。
我们用M[i,j]来表示选用1...i件物品放入容量为j的背包时最大的价值。那样就吧这个情况分成2中情况分析。很简单。用这第i个物品,或者不用。如果不用那么M[i,j]就等于M[i-1,j](如果看不明白可以想象一下M的定义,这里M[i-1,j]的意义就是用1...i-1个物品来装容量为j的背包时的最优策略,也就是不用第i个物品了。) 。那如果用呢?那就是M[i-1, j - si ]+vi。(因为前面的策略已经满了j个容量,所以如果选用第i个物品,就要把总的容量j中减去第i个物品的容量,然后找到对应的M[i-1, j - si]加i的价值) 然后取一个大的值来决定选用那种策略。这个描述虽然有点拗口,但仔细琢磨意思还是直观的。所以这个表达式可以写成
M[i,j] = max { M[i-1,j], M[i-1,j-si]+vi }. 如果我们把他放在二维数组里面的话,可以看出来这里的M[i,j]取决与上一层的M[i-1]中的2个元素。