什么是背包问题:给出一系列矩阵,各自有值和容量,目标是找出总值最大的集合。这个问题的限制是,总容量必须小于等于”背包“的容量。
其实背包问题是一个组合优化问题:
有一个固定大小能够装 10W 的包以及一组有价值和重量的物品,找到一个最佳解决方案来装总重量不超过 10 的总价值最大的方案。
背包问题
我们来分析一下解决的思路,有关物品是否放入,答案其实就两个放入和不放入。我们先初始化几个变量
- n 表示 5 种物品
- c 表示背包的承载能力
- v 表示当前背包中物品的总价值
如图从最后开始循环 - 放入情况
n = 4 c = 5 v =2- 继续向下这样进行递归为 4 放入还是不放入
- 不放入情况
n = 4 c =0 v = 0-
继续向下这样进行递归为 4 放入还是不放入
基本思路
-
我们先用最简单递归来实现上面算法
代码
var weights = [3,4,5];
var values = [2,3,4];
// [[1,5],[2,3],[4,5],[2,3],[5,2]];
function knapSackWithResu(n,c){
var result = 0, a, b;
if(n == 0 || c == 0){
result = 0;
}else if(weights[n] > c){
result = knapSackWithResu(n-1,c)
}else{
a = knapSackWithResu(n-1,c);
b = values[n] + knapSackWithResu(n-1,c-weights[n]);
result = a > b?a:b;
}
// console.log(result);
return result;
}
问题
在上面的递归运算中同样存在着问题,就是重复运算的问题,我们需要在递归过程中将重复运算结果缓存起来以备用从而减少运算的重复来达到优化的目的。
function knapSack(n, c){
var i, w, a, b, ks = [];
for(i = 0; i <= n; i++){
ks[i] = []
}
for(i = 0; i <= n; i++){
for(w =0; w <= c; w++){
if(i ==0 || w ==0){
ks[i][w] = 0;
}else if(weights[i-1] <= w){
a = values[i-1] + ks[i-1][w - weights[i-1]];
b = ks[i-1][w];
ks[i][w] = (a > b) ? a:b;
}else{
ks[i][w] = ks[i-1][w];
}
}
}
return ks[n][c];
}
优化
javascript感谢 cs dojo 分享图片
参考《javascript 数据结构与算法》
网友评论