[Java] 两种方式实现动态规划之 0-1 背包问题

感谢 刘永辉、从杰 及 Arun-Manivannan 的帮助,及其他博主的算法解惑与代码实现。因看目前博文的”0-1 背包”实现较为单一,故在此赘述总结。

方法一:

public class ZeroOnePack {
    public static void main(String[] args) throws Exception {
        int val[] = { 80, 72, 91, 33 };
        int wt[] = { 5, 4, 6, 3 };
        int W = 9;

        System.out.println(pack(val, wt, W));
    }

    public static int pack(int val[], int wt[], int W) {
        // 所能承最大值
        int len = val.length;
        int[][] maxArr = new int[len + 1][W + 1];

        // 最外层循环为物品项
        for (int item = 1; item <= len; item++) {
            // 第二层为仍有空闲空间下的情况
            for (int weight = 1; weight <= W; weight++) {
                // 当前物品的重量是否小于或等于总重
                if (wt[item - 1] <= weight) {
                    // weight - wt[item - 1] 就相当于刨去当前项的重量,在这个约束下求较大值
                    maxArr[item][weight] = Math.max(maxArr[item - 1][weight],
                            maxArr[item - 1][weight - wt[item - 1]] + val[item - 1]);
                } else {
                    maxArr[item][weight] = maxArr[item - 1][weight];
                }
            }
        }
        // Printing the matrix
        for (int[] rows : maxArr) {
            for (int col : rows) {
                System.out.format("%5d", col);
            }
            System.out.println();

        }
        return maxArr[len][W];
    }
}

方法二:

public class ZeroOnePackMy {
    /** 每个物品对应价值 */
    public static int val[] = { 80, 72, 91, 33 };
    /** 每个物品对应重量 */
    public static int wt[] = { 5, 4, 6, 3 };
    /** 袋子最大重量,数组编号从 0 开始 */
    public static int W = 10;
    /** 物品数量,数组编号从 0 开始 */
    public static int N = 4;
    /**
     * 指定编号和重量下,所存放的最大价值(编号有顺序)
* 此处指定 W + 1 是 1.防止越界 2.取到边界值情况 */
public static int[][] maxArr = new int[N][W + 1]; public static void main(String[] args) throws Exception { System.out.println(maxPack(N - 1, W)); for (int i = 0; i < maxArr.length; i++) { for (int j = 0; j < maxArr[0].length; j++) { int mVal = maxArr[i][j]; System.out.format("%5d", mVal); } System.out.println(); } } /** * 参照 http://www.cnblogs.com/sdjl/articles/1274312.html * * @param n * 物品编号 * @param w * 可放重量 * @return */ public static int maxPack(int n, int w) { // 此处可用 -1 作动态规划中的 "备忘录",需前面统一遍历设置 // if (maxArr[n][m] == -1) {} // 编号为 0,即只有一个物品 [对应动态规划中的 "边界"] if (n == 0) { if (w >= wt[0]) { // 如果剩余重量大于 0 号重量,就放进去,最大价值即 0 号价值 maxArr[n][w] = val[0]; } else { // 否则就放不下,此时最大价值为 0 maxArr[n][w] = 0; } } else { if (w >= wt[n]) { // 如果剩余重量大于 n 号重量,就可以放进去 n 号或者放比 n 编号小的一些物品,并取出最大值 // 此处递归实现 maxArr[n][w] = Math.max(maxPack(n - 1, w), maxPack(n - 1, w - wt[n]) + val[n]); } else { // 否则就放不下,此时最大价值就看当前重量下比 n 编号小的物品了 maxArr[n][w] = maxPack(n - 1, w); } } return maxArr[n][w]; } }

参考文章:
1. 动态规划之 01 背包问题(最易理解的讲解)
2. 本周算法:背包问题
3. The Knapsack problem
4. 通过金矿模型介绍动态规划

你可能感兴趣的:(算法)