【问题标题】:Knapsack but exact weight背包但重量准确
【发布时间】:2018-05-16 11:08:25
【问题描述】:

是否有一种算法可以确定具有精确重量 W 的背包? IE。这就像正常的 0/1 背包问题,有 n 个项目,每个项目的重量为 w_i,价值为 v_i。最大化所有物品的价值,但是背包中物品的总重量需要正好有重量W

我知道“正常”的 0/1 背包算法,但这也可以返回重量更轻但价值更高的背包。我想找到最高值但准确的 W 重量。

这是我的 0/1 背包实现:

public class KnapSackTest {
    public static void main(String[] args) {
        int[] w = new int[] {4, 1, 5, 8, 3, 9, 2};  //weights
        int[] v = new int[] {2, 12, 8, 9, 3, 4, 3}; //values

        int n = w.length;
        int W = 15; // W (max weight)

        int[][] DP = new int[n+1][W+1];

        for(int i = 1; i < n+1; i++) {
            for(int j = 0; j < W+1; j++) {
                if(i == 0 || j == 0) {
                    DP[i][j] = 0;
                } else if (j - w[i-1] >= 0) {
                    DP[i][j] = Math.max(DP[i-1][j], DP[i-1][j - w[i-1]] + v[i-1]);
                } else {
                    DP[i][j] = DP[i-1][j];
                }
            }
        }
        System.out.println("Result: " + DP[n][W]);
    }
}

这给了我:

Result: 29

(请问我的问题是否有任何不清楚的地方!)

【问题讨论】:

  • 只需将DP[i][j] = DP[i-1][j]; 切换为DP[i][j] = -infinity
  • @greybeard 哎呀

标签: java algorithm dynamic-programming knapsack-problem


【解决方案1】:

只需在最后一个 else 子句中设置 DP[i][j] = -infinity 就可以了。

其背后的想法是稍微改变递归公式定义来计算:

  • 找到具有精确权重j 到项目i 的最大值。

现在,归纳假设将发生变化,正确性证明将与常规背包非常相似,但修改如下:

DP[i][j-weight[i]] 现在是可以用j-weight[i] 构造的最大值,你可以取项目i,给出DP[i][j-weight[i]] 的值,或者不取它,给出DP[i-1][j] 的值 - 这是在使用精确权重j 和第一个i-1 项目时的最大值。

请注意,如果由于某种原因您无法构造 DP[i][j],则永远不会使用它,因为在查找 MAX 时总是会丢弃值 -infinity。

【讨论】:

  • 对于权重 = {1, 2, 2, 4, 5},值 = {1, 1, 1, 1, 1} 和 W = 6。它给出的答案是 3 其中作为答案是 2(因为精确的重量是通过包含重量为 2 和 4 的项目获得的)。你能帮我解决这个问题吗?
【解决方案2】:

实际上,接受的答案是错误的,正如@Shinchan 在 cmets 中发现的那样。

您只需更改初始dp 状态,而不是算法本身即可获得精确重量的背包。

初始化,而不是:

            if(i == 0 || j == 0) {
                DP[i][j] = 0;
            }

应该是:

            if (j == 0) {
                DP[i][j] = 0;
            } else if (i == 0 && j > 0) { // obviously `&& j > 0` is not needed, but for clarity
                DP[i][j] = -inf;
            }

剩下的和你的问题一样。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-28
    • 2020-07-08
    相关资源
    最近更新 更多