01背包
- 题目:
有N件物品和一个容量为V的背包。放入第i件物品耗费的费用为Ci,得到的价值为Wi。每种物品仅有一件,可选择放或不放(不放就是0,放就是1,谓之01背包)。将哪些物品装入背包可使总价值最大?
- 动态规划分析:
这是一个动态规划求最优的问题。动态规划都可以简单理解为填表法,利用表记录子问题的最优解,达到以空间换时间的目的。一般都可以维护一个记录值的value[][]表和一个记录状态的status[][]表
状态转移方程:
设F[i][v]表示容量为v的背包在选择前i件物品所能获得的最大价值。F[i][v]=max{F[i-1][v],F[i-1][v-ci]+wi} 理解此方程非常重要,理解了此方程就不难理解其他背包问题的方程了。- 解释:当背包容量为v时,第i件物品若不放,则最大价值和放入前i-1件物品的价值是一样的,即可直接参考F[i-1][v]。若放入第i件,则在剩余容量为v-ci的背包中放入前i-1件物品再加上第i件物品的wi,这里容量要减ci的原因是因为要腾出空间放入第i件物品(这里有点解释得不是很清楚,感觉有点不负责任啊,但是算法就是这样,慢慢理解吧)。以下给出两个表,可以模拟以下如何填F[][]表来加深理解状态转移方程。
- 假设输入:
- F[][]表(背包容量为8):
- 解释:当背包容量为v时,第i件物品若不放,则最大价值和放入前i-1件物品的价值是一样的,即可直接参考F[i-1][v]。若放入第i件,则在剩余容量为v-ci的背包中放入前i-1件物品再加上第i件物品的wi,这里容量要减ci的原因是因为要腾出空间放入第i件物品(这里有点解释得不是很清楚,感觉有点不负责任啊,但是算法就是这样,慢慢理解吧)。以下给出两个表,可以模拟以下如何填F[][]表来加深理解状态转移方程。
伪代码:
- 为了别的背包问题能方便调用此函数,一般把for i to N这一层循环去掉(即在函数外循环):
ZeroOnePack(F,C,W)
for v<-0 to V
F[i][v] = max{F[i-1][v],F[i-1][v-ci]+wi}
//然后再
for i<--0 to N
ZeroOnePack(F,ci,wi)