美文网首页
0/1 背包

0/1 背包

作者: HalcyonMoon | 来源:发表于2016-06-29 23:16 被阅读0次

    有 N 件物品和一个容量为 V 的背包。第 i 件物品的费用是 c[i],价值是 w[i]。求解将哪些物品装入背包可使价值总和最大

    f[i][v]表示前 i 件物品恰放入一个容量为 v 的背包可以获得的最大价值,状态
    方程:

    f[i][v] = max{f[i − 1][v], f[i − 1][v − c[i]] + w[i]}
    

    f[i][v] 依赖于 f[i-1][v]和 f[i-1][v-c[i]]

    例子 1:c[] = {4,5,6},  w[]={3,4,5} v=10
    
    0 1 2 3 4 5 6 7 8 9 10
    0 0 0 0 0 0 0 0 0 0 0 0
    1 0 0 0 4 4 4 4 4 4 4 4
    2 0 0 0 4 5 5 5 9 9 9 9
    3 0 0 0 4 5 6 6 9 10 11 11
    例子 2:c[] = { 6,3,5,4,6}, w[]={2,2,6,5,4}, v=10
    
    0 1 2 3 4 5 6 7 8 9 10
    1 0 0 6 6 6 6 6 6 6 6 6
    2 0 0 6 6 9 9 9 9 9 9 9
    3 0 0 6 6 9 9 9 9 11 11 14
    4 0 0 6 6 9 9 9 10 11 13 14
    5 0 0 6 6 9 9 12 12 15 15 15
    public static int zeroOneKnapsack(int c[], int w[], int vol) {
        int len = c.length;
        if (len == 0 || len != w.length) {
            return 0;
        }
    
        int f[][] = new int[len + 1][vol + 1];
        for (int i = 1; i <= len; i++) {
            for (int v = 1; v <= vol; v++) {
                if (i == 0) {
                    f[i][v] = 0;
                    continue;
                }
                f[i][v] = f[i - 1][v];
                if (v >= w[i - 1]) {
                    f[i][v] = Math.max(f[i][v], f[i - 1][v - w[i - 1]] + c[i - 1]);
                }
            }
        }
        return f[len][vol];
    }
    

    可以对空间做优化,用一位数组,由于 f[i][v]依赖 f[i-1][v-c[i]],需要保留上一行 v 之前的记录,所以要从右往左计算。

    public static int zeroOneKnapsackII(int c[], int w[], int vol) {
        int len = c.length;
        if (len == 0 || len != w.length) {
            return 0;
        }
        int f[] = new int[vol + 1];
        for (int i = 1; i <= len; i++) {
            for (int v = vol; v >= w[i - 1]; v--) {
                f[v] = Math.max(f[v], f[v - w[i - 1]] + c[i - 1]);
            }
        }
        return f[vol];
    }
    

    相关文章

      网友评论

          本文标题:0/1 背包

          本文链接:https://www.haomeiwen.com/subject/qaqxjttx.html