【问题标题】:0/1 Knapsack with Minimum Cost0/1 最低成本的背包
【发布时间】:2020-05-09 21:38:15
【问题描述】:

著名的0/1 背包问题侧重于在给定的Weight (W) 中获得最大成本/价值。

上面的代码是这个::

n = cost_array / weight_array size
INIT :: fill 0th col and 0th row with value 0
for (int i=1; i<=n; i++) {
            for (int j=1; j<=W; j++) {
                if (weight[i-1] <= j) {
                    dp[i][j] = Math.max(dp[i-1][j], dp[i-1][j - weight[i-1]] + cost[i-1]);
                }else {
                    dp[i][j] = dp[i-1][j];
                }
            }
        }

回答 :: dp[n][W]

新问题 :: 所以,我们在这里计算最大成本/价值。但是如果我想找到最小的成本/价值怎么办(它仍然是有界的背包)。

我认为问题归结为我如何执行上述INIT 步骤。在循环中,我认为它会保持不变,唯一的区别是 Math.max 变为 Math.min

我用Infinity0 等尝试了INIT 步骤,但无法构建迭代解决方案。 我们怎么可能做到这一点?

【问题讨论】:

  • 只需将每个权重转换为负数,不要更改算法。

标签: dynamic-programming knapsack-problem


【解决方案1】:

@radovix 提到的写答案

  • 将每个权重转换为负数并编写相同的算法。

【讨论】:

  • 嗨,你能分享我最新版本的代码吗?我无法实现它,它正在吞噬我的大脑..
【解决方案2】:

这是一个用 JS 编写的有效算法(最小成本最大背包),时间复杂度为 O(nC),空间复杂度为 O(n+C),而不是空间复杂度为 O(nC) 的明显解决方案DP 矩阵。 给定一个背包实例(I,p,w,C),MCMKP(Minimum-Cost Maximal Knapsack Packing)的目标是找到一个最大背包包装 S⊂I,使所选物品的利润最小化

    const knapSack = (weights, prices, target, ic) => {
      if (weights.length !== prices.length) {
        return null;
      }
      let weightSum = [0],
      priceSum = [0];
      for (let i = 1; i < weights.length; i++) {
        weightSum[i] = weights[i - 1] + weightSum[i - 1];
        priceSum[i] = prices[i - 1] + priceSum[i - 1];
      }
      let dp = [0],
      opt = Infinity;
      for (let i = 1; i <= target; i++) dp[i] = Infinity;
      for (let i = weights.length; i >= 1; i--) {
        if (i <= ic) {
          const cMax = Math.max(0, target - weightSum[i - 1]),
          cMin = Math.max(0, target - weightSum[i - 1] - weights[i - 1] + 1);
          let tmp = Infinity;
          for (let index = cMin; index <= cMax; index++) {
            tmp = Math.min(tmp, dp[index] + priceSum[i - 1]);
          }
          if (tmp < opt) opt = tmp;
        }
        for (let j = target; j >= weights[i - 1]; j--) {
          dp[j] = Math.min(dp[j], dp[j - weights[i - 1]] + prices[i - 1]);
        }
      }
      return opt;
    };
    
    knapSack([1, 1, 2, 3, 4],[3, 4, 6, 2, 1],5,4);

在上面的以下代码中,我们定义了一个关键项目,它的权重给出了任何可行解决方案之外的最小可能项目的严格上限。 关键项的索引,即第一个超出容量的项的索引,假设所有 i ≤ ic 也将被采取。 opt 是最优解。 观察项目 {1, . . . , i - 1} 确定背包的剩余容量 (以 cMax 给出)必须使用 {i + 1, . . . , n},而 cMin 是由以下事实决定的:包装必须是最大的,并且项目 i 是从解决方案中取出的最小项目

【讨论】:

  • 嗨,我真的不明白 ic 在做什么。你能详细解释一下吗?例如,我有 prices = [10, 15, 20, 25, 30] 和 weights = [200, 200, 500, 250, 300] 。我给容量为 700 所以目标,但我应该给 ic 哪个值,以便我可以在填充容量 = 35 时获得最小值
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-20
  • 1970-01-01
  • 1970-01-01
  • 2011-12-28
  • 2013-01-03
  • 1970-01-01
相关资源
最近更新 更多