应某些童鞋的要求,我在接下来的几篇博文中详细的介绍几种动态规划的模型。
这次是第一种,背包。
在动规中有一类非常经典的问题叫背包问题,分为01背包、完全背包、多重背包。
- 01背包:给你n个物品,每个物品有自己的价值v[i]以及重量w[i],选择一种物品就能获得相应的价值,但背包容量有限,只能装总重量不超过m的物体,每个物品只能选一次,所以你需要选择适当的物品,使得价值和最大,求此价值和。
f[i][j]表示第i个物品,重量和为j。由于第i个物品分为取和不取两种,则
f[i][j]=max(f[i-1][j],f[i-1][j-w[i]]+v[i]);
但细心地读者看出来了,这样做的空间复杂度为o(nm),还有进一步优化的空间。
注意到,f[i][j]只和i-1层有关,暨算f[i][j]时,f[i-2]等层是无用的。我们不妨用滚动数组优化。在注意到但由于这题的特殊性,求f[i][j]时,所有的f[i-1][x](x>j)是用不到的,所以可以进一步优化,用一维数组即可。
f[j]=max(f[j],f[j-w[i]]+v[i]) (1<=i<=n, w[i]<=j<=m)
(标程见我博文最后附上的网盘地址。) - 完全背包:01背包:给你n个物品,每个物品有自己的价值v[i]以及重量w[i],选择一种物品就能获得相应的价值,但背包容量有限,只能装总重量不超过m的物体,每个物品能选任意次,所以你需要选择适当的物品,使得价值和最大,求此价值和。
类似于01背包,完全背包的过程与01背包非常之想,也是用f[i][j]表示第i个物品,重量和为j。(动规方程留给读者自己去写)
也同样可以有空间优化。而且优化后的动归方程也几乎一模一样。
f[j]=max(f[j],f[j-w[i]]+v[i]) (1<=i<=n, w[i]<=j<=m)
(标程见我博文最后附上的网盘地址。注意比较两个程序的区别)。 - 多重背包:就是说每个物品有只能选一件和能无限选之分,具体的做法参考以上两种做法,结合起来即可。