0-1 背包问题
问题: 有Num个物品,每个物品的重量为weight[i],每个物品的价值为value[i]。现在有一个背包,它所能容纳的重量为 M ,问:当你面对这么多有价值的物品时,你的背包所能带走的最大价值是多少?
解决方法: 采用动态规划的方法解决。
01背包的状态转换方程
f[i,j] = Max{ f[i-1,j-Weight[i]]+Value[i] ( j >= Wi ), f[i-1,j] }
看不懂这个公式很正常,待会看了做法就知道了。
给一个具体的题目:
有a,b,c,d,e 5个物品。他们的重量和价值是(4, 6) (5,4) (6,5) (2,3) (2,6) ,
然后用一个大小为10的背包装他们,要求价值最大化。
这个时候我们借助一张表来解题
what can in bug | weight | value | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
a | 4 | 6 | |||||||||||
a,b | 5 | 4 | |||||||||||
a,b,c | 6 | 5 | |||||||||||
a,b,c,d | 2 | 3 | |||||||||||
a,b,c,d,e | 2 | 6 |
what can in bug意思就是说这一行代表什么能在包里,当我们填第一行的时候,只能是a在包,我们不考虑其他的b,c,d,e,就这样一行加一个物品考虑,一直往下。
按照这个思路:
第一行,0,1,2,3 因为都不满足物品重量为 4的要求,所以填0,而4 - 10 填物品a的value 6。
第二行,0,1,2,3不满足物品a ,b重量的需求,同样为0,但4,5上一行已经能满足的,这一行当然能满足,所以照抄下来。到了6 就有两种选择了,一种是采用上一行的结果,另一种是放这次加入物品b,两种取价值最大。
以此类推。
为了便于理解,我打印了过程给大家看:
以下是C++代码,打印过程被我注释,可以打开去看下整个dp的过程。
#include <iostream>
#define max(x,y) (x)>(y) ? (x) : (y)
using namespace std;
int main(int argc, const char * argv[])
{
//数据定义部分
int Num; //物品数量
int M; //背包容量
cin >> Num;
cin >> M;
int weight[Num],f[Num][M+1],value[Num];
for (int i=0;i<Num; i++) {
cin >> weight[i] >> value[i];
}
// //赋初值0,便于打印过程