贪心算法-背包问题

87 阅读2分钟

什么是贪心算法

基本概念

贪心算法,又称贪婪法是寻找问题最优解的常用方法,它将求解过程分成若干个步骤,在每个步骤都应用贪心原则,选取当前状态下最好的或最优的选择(局部最有利的选择),并以此希望最后堆叠出的结果也是最好或最优的解。对于特定问题是非常有效的方法。

决策方案

贪婪法的每次决策都以当前情况为基础并根据某个最优原则进行选择,不考虑当前决策的后续影响,不考虑整体上是否有其他可能得情况。

基本思想

  1. 建立对问题精确描述的数学模型,包括定义最优解的原则;
  2. 将问题分解为一系列子问题,同时定义子问题的最优解结构;
  3. 应用贪心原则确定每个子问题的局部最优解,并根据最优解的模型,用子问题的局部最优解堆叠出全局最优解。

背包问题(非0-1背包)

给定n种物品和一个背包。物品i的重量是weight[i],其价值为value[i],背包最大容量为grossWeight。应如何选择装入背包的物品(每件物品可以全装也可以只装一部分),使得装入背包中物品的总价值最大?

问题分析

基于问题给出的“每件物品可以全装也可以只装一部分”,我们可以得知一个物品可以分割装。又由于需要在容量确定的情况下尽可能的装入价值最大的物品,因此此处可运用贪心算法装入(value/weight)单位重量价值最高的物品。

const KnapsackProblem = (weight = [], value = [], grossWeight = 0) => {
  const wLength = weight.length;
  const vLength = value.length;
  if (
    wLength === 0 ||
    vLength === 0 ||
    grossWeight === 0 ||
    wLength !== vLength
  ) {
    throw new Error("Invalid data!");
  }

  //把物品价值和重量的两个一维数组转化成一一对应的二维数组
  const newArr = weight.map((item, index) => {
    return (item = [item, value[index]]);
  });

  //降序排序
  const sortArr = newArr.sort((a, b) => {
    return b[1] / b[0] - a[1] / a[0];
  });

  let i = 0;
  let result = 0;
  //贪心算法,先从价值最大的物品开始装
  while (grossWeight > 0) {
    //当背包容量不足存放一个完整物品时,需要分割
    if (sortArr[i][0] > grossWeight) {
      result += grossWeight * (sortArr[i][1] / sortArr[i][0]);
      break;
    }
    grossWeight -= sortArr[i][0];
    result += sortArr[i][1];
    ++i;
  }
  return result;
};

console.log('最大价值为:',KnapsackProblem([25, 40, 55, 45, 35, 15, 30], [20, 10, 15, 40, 50, 25, 5], 200));