动态规划——0-1背包问题(JavaScript解法)

背包问题是一个组合优化问题,题目描述如下:
给定一个固定大小、容量为C的背包,以及一组有价值和重量的物品,找出一个最佳的解决方案,使得装入背包的物品重量小于W,且价值最大。
通俗的描述就是:
你有一个书包,还有一堆物品摆在你的面前,手机、电脑、平板、砖头,而你的书包只能装5斤东西,装哪些东西最赚?

理解了题目意思我们再来看一个输入输出例子

输入

weight:[2,3,4,5,9] //重量
values:[3,4,5,8,10] //价值
C:20 //背包容量
物品 价值 重量
0 3 2
1 4 3
2 5 4
3 8 5
4 10 9

输出

选取物品0、2、3、4,总价值为3+5+8+10 = 26

maxValue:26

我们假设公式B(k,c)表示有k个物品,容量为C时的最大价值
问题便转为求B(4,20)的值

  1. 当k指向第4个物品时,重量为9,明显小于背包容量C,所以我们可以将物品4装入背包,故
    B(4,20) = B(3,20-9)+10 = B(3,11)+10

别忘了我们追求的是最大价值,如果把物品4装进去那容量就变小了,装不进其他物品,所以对于小于背包容量的物品,我们有两个选择

  • 装进去
    B(4,20) = B(3,20-9)+10 = B(3,11)+10
  • 不装
    B(4,20) = B(3,20)

如果物品4的重量为100,明显超出背包容量时,那B(4,20)等于多少呢?
既然装不下,那我们就忽略掉物品4,让k指针指向上一个物品,容量不变
B(4,20) = B(3,20)

通过以上分析我们可以得出B(k,c)的递归公式


我们来分析B(4,20)的执行过程,可以发现实际上这个公式是二叉树的形式


看懂了上图,这题可以使用递归方法解决,但更好地解法是使用动态规划。
动态规划是一种将复杂问题分解成更小的子问题来解决的优化技术

算法如下:

function kanpSack(capacity, weights, values, n) {
  var a,b,KS = []
   
//首先,初始化用于寻找解决方案的矩阵KS[n+1][capacity+1]
  for (var i = 0; i <= n; i++) {
    KS[i] = [];
  }
  for (var i = 0; i <= n; i++) {
    for (var w = 0; w <= capacity; w++) {
      if (i === 0 || w === 0) {
      //让第一行和第一列为0,因为第一行和第一列表示容量为0或没有物品可装
        KS[i][w] = 0; 
      } else if (weights[i - 1] > w) {
        KS[i][w] = KS[i - 1][w]; //当前物品重量大于当前容量
      } else {
       //当前物品重量小于当前容量,有两个选择,装或者不装,取价值最大的
        a = KS[i - 1][w - weights[i - 1]] + values[i - 1]; //装入这个物品后的总价值
        b = KS[i - 1][w]; //不装
  
        KS[i][w] = a > b ? a : b;
      }
    }
     
  }
  return KS[n][capacity];
}


测试

var values = [3,4,5,8,10];
var weights = [2,3,4,5,9];
var capacity = 20;
var n = values.length;
console.log(kanpSack(capacity, weights, values, n)); //26

这个算法构造了一个二维表格KS,存储了递归过程的中的值,即用for循环代替了递归,表格右下角的最后一个格子就是问题的解。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 专业考题类型管理运行工作负责人一般作业考题内容选项A选项B选项C选项D选项E选项F正确答案 变电单选GYSZ本规程...
    小白兔去钓鱼阅读 9,077评论 0 13
  • 目录 1.问题描述1.1 问题描述1.2 问题的数学表示(规划类问题,此种表示可以转换为回溯法)1.3 三种方法的...
    王侦阅读 19,810评论 0 2
  • 0 1 背包问题描述 有n个物品,它们有各自的体积和价值,现有给定容量的背包,如何让背包里装入的物品具有最大的价值...
    justonemoretry阅读 664评论 1 0
  • 选择题部分 1.(),只有在发生短路事故时或者在负荷电流较大时,变流器中才会有足够的二次电流作为继电保护跳闸之用。...
    skystarwuwei阅读 13,608评论 0 7
  • 回溯算法 回溯法:也称为试探法,它并不考虑问题规模的大小,而是从问题的最明显的最小规模开始逐步求解出可能的答案,并...
    fredal阅读 13,808评论 0 89