动态规划—01背包问题

作者: 宛丘之上兮 | 来源:发表于2018-12-06 17:29 被阅读4次

    01背包问题属于经典的动态规划问题,场景描述如下:

    形象描述:贼,夜入豪宅,可偷之物甚多,而负重能力有限,偷哪些才更加不枉此行?

    进一步抽象的话,就是:
    给定n个物品,每种物品都有自己的重量w_i和价值v_i,在限定的总重量/总容量C内,选择其中若干个(也即每种物品可以选0个或1个),设计选择方案使得物品的总价值最高

    顶级抽象描述就是数学语言了,数学语言描述如下:
    条件:
    1: n个数对(w_i,v_i)_{1 \le i \le n}
    2: 正整数C
    求解0-1规划问题:
    max \sum_{i=1}^{n}x_iv_i, \quad s.t. \sum_{i=1}^{n}x_iw_i \le C, \quad x_i \in \{0,1\}

    0-1背包问题子结构:选择一个给定物品i,则需要 比较 选择i 的形成的子问题的最优解 与 不选择i 的子问题的最优解。分成两个子问题,进行选择比较,选择最优的。

    0-1背包问题递归过程:设有n个物品,背包的重量为totalWeighttable[i][w]为最优解。即只需要一个判断三条件的公式就能求出最优解:
    table[i,w]= \begin{cases} 0,& \mbox{if }i== 0\mbox{ or } w==0 \\ table[i-1,w], & \mbox{if } w_i > w \\ max(table[i - 1][w], table[i - 1][w - w_i] + v_i), & \mbox{if } i > 0 \mbox{ and } w \ge w_i \end{cases}

    有了这个判断三条件的公式,代码实现起来就比较轻松了,Java实现源码如下:

    public class CB {
        public static void main(String[] args) {
            int totalWeight = 10;                    //物品个数,背包容量
            Bean[] data = new Bean[]{new Bean(0, 0),
                    new Bean(2, 6), new Bean(2, 3), new Bean(6, 5), new Bean(5, 4), new Bean(4, 6)};
            System.out.println(getMaxValue(data, totalWeight));
        }
    
        public static int getMaxValue(Bean[] data, int totalWeight) {
            int n = data.length;
            int[][] table = new int[n][totalWeight + 1];
            for (int i = 1; i < n; i++) { //物品
                for (int w = 1; w <= totalWeight; w++) {  //背包大小
                    if (data[i].weight > w) {
                        //当前物品i的重量比背包容量j大,装不下,肯定就是不装
                        table[i][w] = table[i - 1][w];
                    } else { //装得下,Max{装物品i, 不装物品i}
                        table[i][w] = Math.max(table[i - 1][w], table[i - 1][w - data[i].weight] + data[i].value);
                    }
                }
            }
            for (int f = 0; f < table.length; f++) {
                System.out.println(Arrays.toString(table[f]));
            }
            return table[n - 1][totalWeight];
        }
    
        static class Bean {
            int weight = 0;
            int value = 0;
    
            Bean(int w, int v) {
                weight = w;
                value = v;
            }
    
            @Override
            public String toString() {
                return weight + "  " + value;
            }
        }
    }
    

    我们初始化五个数对Bean(2, 6), Bean(2, 3), Bean(6, 5), Bean(5, 4), Bean(4, 6),总重量totalWeight=10,算法的最终输出如下:

    相关文章

      网友评论

        本文标题:动态规划—01背包问题

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