一. 01背包
题目:有N件物品和一个容量为V的背包,第i件物品的重量是w[ i ],价值是value[ i ].求解将哪些物品装入背包可使这些物品的重量总和不超过背包容量,且价值总和最大.
01背包, 最简单的背包问题,背包问题的动态转移方程都是从01背包的动态转移方程转化过来的.故而01背包是最基础的背包问题.其特点是:每种物品只有一件,可以选(1)可以不选(0).选择为1,不选择为0.故此从未01背包.用子问题定义状态dp (i, v ),表示前i件物品恰装入容量为v的背包中可获得的最大价值.其动态转移方程为: dp( i, v ) = max( ( dp( i-1, v ), dp( i-1, v - w[ i ] + value[ i ] ) );这里肯定就会有人问到这个i-1是从何而来.首先我们来明确一点,在写这个状态之前,我们需要清楚,我们要表示前i件物品恰装入容量为v的背包中.故此当选择不装第i件(0)时 dp( i, v )就等于上一状态 dp( i-1, v )的值.而当我选择装第i件(1)时, dp(i, v) 就等于上一状态的value的值+第i次的价值,容量则减去第i个的容量.故此此状态转移方程便诞生了...
我们来看看用二维数组的童鞋 c[ i ][ j ]里究竟是存了些神马,来看看过程是神马样子的.小康子,给各位亲们上组样例输入输出赏玩赏玩!
输入:
4(个数n) 10(容量V)
5 1 4 3 (各个物品的重量w
[ i ]
)
40 10 25 30 (各个物品的价值value[ i ])
输出:
80
(真心不想画图弄表格,我真心很懒- -...唉...命啊! 苍天啊...)
我们先来看 c[1][5] == 40 是肿么来的吧~ 当代表容量的j == 5 的时候就可以放下第一个物品,那么我们c[1][5]自然要把第一个物品的value[1]纳入囊中!为什么之前c[1][ j<5 ] == 0 推理可知:容量为1-4时,放不下重量为5的第一个物品.
我们再来看看为什么c[2][5] == 40 因为我们选取的要是最大值,即最优解,所以当j==5时,贪心的我们,就必然把第一个物品纳入囊中.当j==6时,既能放下物品一又能放下物品二,作为21世纪进步青年,作为21世纪的大学生我们有责任去肩负祖国给予我们的责任...(额..扯远了~不远~~我们的责任就是能拿多少就拿多少- -!!!)额...是的,既然能放下物品一和物品二我们就需要把物品一,二全部都囊括在自己的口袋中了!同理可证..下面的那些数字,想必就不用我这只小菜去叙述了吧...(我真的很懒- -打这么多字都累死我老人家了!)
再让我们看看这道题的优化,即用一维数组表示:
for( i=0; i<n; i++ ){
for( j=V; j>=w[ i ]; j-- )
c[ j ] = max(v[ j ], v[ j-w[ i ] ] + value[ i ] );
}
其实这串代码只是把放不下第i个物品的j去掉,额..没看懂吧..额..我都快蒙圈了- -我们拿第一个物品为例,我们可以去掉j == 1,2,3,4 因为它们放不下第一个物品.这就是出现这种循环边境的原因.
01背包可以完结了吧- -???我真心打字打得灰常累- -!!! 额...不管了...就这样了...完结了- -...不过话说来几个题吧~玩玩也好...HDOJ 2602 2955(需要脑袋转个弯儿) 1864 (基本上算是小变形..慢慢搞..) 1203 (务必好好想想...可以吧c设定为得不到的概率,那么1-c[V]... 额...自己做吧- -你懂得!)