背包问题 (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件物品可不可以放入。

  1. j < w[i],不放,f[i][j] = f[i-1][j]
  2. j >= w[i],可以放,但是考虑代价
    f[i][j] = max(f[i][j],f[i][j-c[i]]+w[i])
  3. 总结
    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]}
这就是两种背包的区别。

posted @ 2021-01-23 17:54  Paranoid5  阅读(68)  评论(0编辑  收藏  举报