背包问题 (1)
背包问题
1.01背包
有N件物品和一个容量为V的背包。第i件物品的费用是c[i],价值是w[i]。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。
Hdu 2602 Bone Collector
样例输入:
5 10
1 2 3 4 5
5 4 3 2 1
样例输出:
14
定义:f[i][j]表示前i件恰好放入一个容量为j的背包可以获得的最大价值的。
状态转移方程:f[i][j] = max{f[i-1][j],f[i-1][j-c[i]]+w[i]}
答案是:f[n][v]。
下表就是DP表(md打表真的好麻烦...):
w[i]\j | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
---|---|---|---|---|---|---|---|---|---|---|---|
5 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 |
4 | 0 | 0 | 0 | 0 | 2 | 2 | 2 | 2 | 2 | 3 | 3 |
3 | 0 | 0 | 0 | 3 | 3 | 3 | 3 | 5 | 5 | 5 | 5 |
2 | 0 | 0 | 4 | 4 | 4 | 7 | 7 | 7 | 7 | 9 | 9 |
1 | 0 | 5 | 5 | 9 | 9 | 9 | 12 | 12 | 12 | 12 | 14 |
表1
f[i][j]是由f[i-1][j]和f[i-1] [j-c[i]]两个子问题递推而来,能否保证在推f[i][j]时(也即在第i次主循环中推f[j]时)能够得到f[i-1][j]和f[i-1][j -c[i]]的值呢?
从V->0的顺序来递推就行了。
递推公式为f[j]=max{f[j],f[j-c[i]]+w[i]};
我们都知道 f[i-1][j-c[i]] ,f[i-1][j] 可以推出f[i]
但是为什么0~V是不行的呢?
下表是0~V的表。
w[i]\j | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
---|---|---|---|---|---|---|---|---|---|---|---|
5 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 2 |
4 | 0 | 0 | 0 | 0 | 2 | 2 | 2 | 2 | 4 | 4 | 4 |
3 | 0 | 0 | 0 | 3 | 3 | 3 | 6 | 6 | 6 | 9 | 9 |
2 | 0 | 0 | 4 | 4 | 8 | 8 | 12 | 12 | 16 | 16 | 20 |
1 | 0 | 5 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 |
表2
很明显这是不行的。因为顺推的时候,f[j]=max{f[j],f[j-c[i]]+w[i]},f[j-c[i]]表示的是fi[j-c[i]]而不是fi-1[j-c[i]]。如果还是不懂,之后再01背包和完全背包中的解释会有对比理解。
2.完全背包
有N种物品和一个容量为V的背包,每种物品都有无限件可用。第i种物品的费用是c[i],价值是w[i]。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。
Uva 674 Coin Change
定义:f[i][j]表示前i件恰好放入一个容量为j的背包可以获得的最大价值的。
递推方程:
当前背包为j,我们考虑第i件物品可不可以放入。
- j < w[i],不放,f[i][j] = f[i-1][j]
- j >= w[i],可以放,但是考虑代价
f[i][j] = max(f[i][j],f[i][j-c[i]]+w[i]) - 总结
f[i][v] = max
注意:这里的是f[i][j-c[i]] 而01背包是f[i-1][j-c[i]],这就是他们在二维数组上的不同
那么一维数组是什么呢?就是在之前01背包讨论时的顺推!!!
那么打表也就是表2。
这究竟是为什么呢?
3.01背包与完全背包的区别
在二维数组01背包的递推式是这样的:
f[i-1][j-c[i]](1)——— f[i-1][j](2)
———————————— f[i][j](4)
完全背包是这样的:
———————————— f[i-1][j](2)
f[i][j-c[i]](3)———— f[i][j](4)
也就是说,在使用一维数组的时候,需要注意,f[j-c[i]]究竟表达的是什么。
如果是顺推,计算顺序是1,2,3,4(上图标号)
f[j]表达顺序是 2,4,f[j-c[i]]表达顺序是1,3
此时:f[j](4)=max{f[j](2),f[j-c[i]](3)+w[i]}
如果是逆推,计算顺序是2,1,4,3(上图标号)
f[j]表达顺序是 2,4,f[j-c[i]]表达顺序是1,3
此时:f[j](4)=max{f[j](2),f[j-c[i]](1)+w[i]}
这就是两种背包的区别。