本文仅供参考学习使用,谢谢
01背包:
设计一个动态规划问题需要首先搞清楚他的:
- 同质子结构
- 状态转移方程
- 备忘录(即动态规划中动态存储数据的东西)
如果将背包问题用方程 F(w,i) 表示 w 为背包容量,i 为物品个数
则对于每一个物品,只需要考虑装入背包 or 不装入背包这两个情况
对于 F(4,3)=9 I=3(weight=8,value=9)
是由F(4,3) = MAX{ F(4,2) , F(4-1,2)+9 } = 9 得来的
F(w,i) = MAX{ F(w,i-1) , F(w-i.weight,i-1)+i.value }
补充:需要条件判断 w>=i.weight 即w-i.weight>=0
-∞ (w<0) | |
---|---|
f(w,i)= | 0 (w=0 or i=0) |
max{ vi+f( w-wi , i-1 ) , f( w , i-1 ) } (w>0 && I>0) |
01背包有几个非常严肃的情况
- 如果01背包的备忘录是一个一维数组,那么每一个物品放入时,若正序(即1~W)放入 当前的 第i个物品 会变成完全背包,如果想要避免这个问题。只需要将其倒叙放入(即W~1)状态方程不变。
- 如果01背包的备忘录是一个二维数组,则正序倒叙都可以,都不会演变成完全背包。
- 同理若为二维背包问题,当二维背包的备忘录是一个三位数组时,不会演变成完全背包。当备忘录是一个二维数组时 正序放入物品会演变成完全背包,倒叙则不会。
如下图所示,用一维数组作备忘录,可能出现多次加当前物品的value的情况,这样的话就变成了一个完全背包问题。😏😏😏
完全背包:
- 物品有无限件
- 不是放不放,而是放几个的问题(当然有n种物品)
-∞ (w<0) | |
---|---|
f(w,i)= | 0 (w=0 or i=0) |
max{ k*vi+f( w- k * wi , i-1 ) , f( w , i-1 ) } (w>0 && I>0 && 0<k<=w / wi ) |
多重背包:
- 第 i 个物品有 n 个
- 放几个的问题,但不能超过n
-∞ (w<0) | |
---|---|
f(w,i)= | 0 (w=0 or i=0) |
max{ k*vi+f(w- k * wi,i-1) , f(w,i-1) } (w>0 && I>0 && 0<k<=min{ni,w/wi) } |
分组背包:
- 物品被分成若干组,每组中的物品相互冲突。
- 每组中要么选一个,要么一个不选。
-∞ (w<0) | |
---|---|
f(w,i)= | 0 (w=0 or i=0) |
max{ max{vj+f( w-wj , i-1 )} , f( w , i-1 ) } (w>0 && I>0 && j 属于 I 组) |
二维背包:
顾名思义就是比 01背包 多了一个限制条件比如01背包只有重量限制,二维背包在重量限制的基础上增加一个体积限制。该问题的思路和01背包一样,只不过多增加一维(三维)去理解就可以了。
但是在编写代码的时候我遇到了看不懂的的错误,所以我将三位数组优化成了二维数组去动态存储数据。