JAVA算法:背包问题算法分析(汇总)
背包问题(Knapsack problem)是一种组合优化的NP完全问题。问题可以描述为:给定一组物品,每种物品都有自己的重量和价格,在限定的总重量内,我们如何选择,才能使得物品的总价格最高。问题的名称来源于如何选择最合适的物品放置于给定背包中。
背包问题的一般描述
我们有 n 种物品,物品 j 的重量为 wj,价格为 pj 。
我们假定所有物品的重量和价格都是非负的。背包所能承受的最大重量为 W。
如果限定每种物品只能选择 0个 或 1个,则问题称为 0-1 背包问题。
可以用公式表示为:
最大化
受限于
如果限定物品 j 最多只能选择 bj 个,则问题称为有界背包问题。
可以用公式表示为:
最大化
受限于
如果不限定每种物品的数量,则问题称为无界背包问题。
各类复杂的背包问题总可以变换为简单的 0-1 背包问题进行求解。
背包问题实例描述
有n个物品,它们有各自的体积(或者重量)和价值,现有给定容量的背包,如何让背包里装入的物品具有最大的价值总和?
假设:我们有4个物品,背包的最大容量为8。
背包问题的解决过程
在解决问题之前,为描述方便,首先定义一些变量:Vi表示第 i 个物品的价值,Wi表示第 i 个物品的体积,定义V(i,j):当前背包容量 j,前 i 个物品最佳组合对应的价值,同时背包问题抽象化(X1,X2,…,Xn,其中 Xi 取0或1,表示第 i 个物品选或不选)。
1、建立模型,即求max(V1X1+V2X2+…+VnXn);
2、寻找约束条件,W1X1+W2X2+…+WnXn<capacity;
3、寻找递推关系式,面对当前商品有两种可能性:
包的容量比该商品体积小,装不下,此时的价值与前i-1个的价值是一样的,即V(i,j)=V(i-1,j);
还有足够的容量可以装该商品,但装了也不一定达到当前最优价值,所以在装与不装之间选择最优的一个,即V(i,j)=max{V(i-1,j),V(i-1,j-w(i))+v(i)}。
其中V(i-1,j)表示不装,V(i-1,j-w(i))+v(i) 表示装了第i个商品,背包容量减少w(i),但价值增加了v(i);
由此可以得出递推关系式:
j<w(i) V(i,j)=V(i-1,j)
j>=w(i) V(i,j)=max{V(i-1,j),V(i-1,j-w(i))+v(i)}
这里需要解释一下,为什么能装的情况下,需要这样求解(这才是本问题的关键所在!):
可以这么理解,如果要到达V(i,j)这一个状态有几种方式?
肯定是两种,第一种是第i件商品没有装进去,第二种是第i件商品装进去了。没有装进去很好理解,就是V(i-1,j);装进去了怎么理解呢?如果装进去第i件商品&#