【问题标题】:Knapsack - determining set from total value背包 - 从总值确定集合
【发布时间】:2015-04-24 07:29:07
【问题描述】:

在看到this 讲座后,我创建了以下背包代码。在讲座中,教授说从最佳值(19:00 分钟)确定集合很容易,但是我找不到如何去做。我在代码中提供了一个将值相加为 21 的示例,如何从该值确定集合(在本例中为 12、7、2)?

/*
    v = value
    w = weight
    c = capacity
 */
function knapsack(v, w, c) {
    var n = v.length,
        table = [];
    // create two-dimensional array to hold values in memory
    while (table.length <= c) {
        table.push([]);
    }

    return ks(c, 0);
    function ks(c, i) {
        if (i >= n) {
            table[c][i] = 0;
            return table[c][i];
        }
        if (c < w[i]) {
            if (table[c][i+1] === undefined) {
                table[c][i + 1] = ks(c, i + 1);
            }
            return table[c][i + 1];
        }
        else {
            if (table[c][i + 1] === undefined) {
                table[c][i + 1] = ks(c, i + 1);
            }
            if (table[c - w[i]][i + 1] === undefined) {
                table[c - w[i]][i + 1] = ks(c - w[i], i + 1);
            }
            return Math.max(table[c][i + 1], v[i] + table[c - w[i]][i + 1]);
        }
    }
}

//This is a test case
var v = [7, 2, 1, 6, 12];
var w = [3, 1, 2, 4, 6];
var c = 10;
var result = knapsack(v, w, c);
document.getElementById("solution").innerHTML = result;
&lt;pre&gt;Optimal solution value is: &lt;span id="solution"&gt;&lt;/span&gt;&lt;/pre&gt;

【问题讨论】:

    标签: javascript algorithm dynamic-programming knapsack-problem


    【解决方案1】:

    这根本不容易。确定某组数字的子集是否具有一定的和称为subset sum problem,它是 NP 完全的,就像背包本身一样。只保留指向子问题解决方案的指针会容易得多,您可以从中构造更大的子问题的最佳解决方案。这样你就可以沿着全局最优解的指针往回走,找到给你最优值的实际集合。

    (编辑:如 j_random_hacker 在 cmets 中所述,一旦我们有了 DP 表,我们实际上可以确定在 O(n2) 时间内给出最优值的集合,方法是从最佳解决方案并通过表格向后工作,考虑可能是最后添加的每个可能的项目,并检查该解决方案是否与预期值匹配。)

    另外,我建议您观看一些不同的讲座。这家伙提出了一些奇怪的说法,比如 O(nc)——n 个项目,c 容量——远小于 O(2n),当 c 很大时,这根本不是真的. (其实这叫做pseudo-polynomial time解,在输入的长度上它仍然是指数级的,以比特为单位。)

    【讨论】:

    • 你能举例说明如何在这段代码中添加指向解决方案的指针吗?
    • @user3836205 您可以存储带有父项、项和值的对象,而不是只存储一个数字。这里的 value 是您当前已经在计算的数字, parent 是您扩展的子问题的解决方案,以获得当前子问题的解决方案,而 item 就是您添加的项目。
    • 我没看过讲座,但我想说准确的措辞在这里很重要。正如您所说,仅从数字确定子集确实是 NP-hard,但仅使用 一种用于查找数字的算法 来确定子集可以说是“容易”的,因为它只是“多项式更难”比找到一个数字:...
    • ...设原解为y_0,原容量为c_0。删除一些项目 x_i,将容量减少 w_i 并解决它。如果答案 = y - v_i,那么 x_i 是某个最优解的一部分,您应该将容量保留在 c_0 - w_i;否则不是,您应该将容量设置回 c_0。无论哪种方式, x_i 都会被删除。继续删除单个项目并重新解决,直到没有剩余。这需要 n 倍的时间来解决单个实例。
    • @j_random_hacker:讲师的字面意思是“一旦我们知道 [最佳] 值是什么,就很容易回过头来计算 [the] set 是什么”。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多