01背包四种方式实现

暴力递归

    /**
     * 暴力枚举
     *
     * @param i        输入规模
     * @param capacity 背包容量
     * @return 背包最大价值
     */
    public int forceKnapsackSR(int i, int capacity) {
        // 超重了
        if (capacity < 0) {
            return Integer.MIN_VALUE;
        }
        // 每一件商品都被选择完了
        else if (i < 1) {
            return 0;
        }
        int p1 = forceKnapsackSR(i - 1, capacity - c[i]) + v[i];
        int p2 = forceKnapsackSR(i - 1, capacity);
        // 选择第i件商品
        // 该商品被算在其中
        if (p1 > p2) {
            plan[i] = true;
            // 需要进行回溯
            return forceKnapsackSR(i - 1, capacity - c[i]) + v[i];
        } else {
            plan[i] = false;
            return forceKnapsackSR(i - 1, capacity);
        }
    }
        /**
     * 获得最优背包方案
     */
    public void getPlan() {
        for (int i = 1; i < plan.length; i++) {
            // 如果被选中
            if (plan[i]) {
                System.out.print(" " + i + "件");
            }
        }
    }

记忆数组优化

 /**
     * 使用记忆数组
     *
     * @param i        输入规模
     * @param capacity 背包容量
     * @return 背包最大价值
     */
    public int memoryKnapsackSR(int i, int capacity) {
        // 超重了
        if (capacity < 0) {
            return Integer.MIN_VALUE;
        }
        // 每一件商品都被选择完了
        else if (i < 0) {
            return 0;
        }
        if (memory[i][capacity] != 0) {
            return memory[i][capacity];
        }
        int p1 = memoryKnapsackSR(i - 1, capacity - c[i]) + v[i];
        int p2 = memoryKnapsackSR(i - 1, capacity);
        // 选择第i件商品
        // 该商品被算在其中
        memory[i][capacity] = Math.max(p1, p2);
        return memory[i][capacity];
    }

动态规划

/**
     * 动态规划
     *
     * @param n        输入规模
     * @param capacity 背包容量
     */
    public int dynamicKnapsackSR(int n, int capacity) {
        // 枚举每一种商品
        for (int i = 1; i <= n; i++) {
            // 枚举商品的每一种可能重量从 1 ——> capacity
            for (int j = 1; j <= capacity; j++) {
                // 在容量不超出的情况下,选择下件商品使得背包的价值更大
                if (c[i] <= j && v[i] + memory[i - 1][j - c[i]] > memory[i - 1][j]) {
                    memory[i][j] = v[i] + memory[i - 1][j - c[i]];
                    rec[i][j] = 1;
                } else {
                    memory[i][j] = memory[i - 1][j];
                    rec[i][j] = 0;
                }
            }
        }
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= capacity; j++) {
                System.out.print(" " + memory[i][j] + " ");
            }
            System.out.println();
        }

        return memory[n][capacity];
    }
     /**
     * 获得动态规划的最佳方案
     *
     * @param n        输入规模
     * @param capacity 背包容量
     */
    public void getBest(int n, int capacity) {
           // 打印方案表
        System.out.println("-----------------------------");

        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= capacity; j++) {
                System.out.print(rec[i][j] + " ");
            }
            System.out.println();
        }
        System.out.println("-----------------------------");
        // 这里需要逆序
        for (int i = n; i >= 0; i--) {
            if (rec[i][capacity] == 1) {
                System.out.print(" 第" + i + "件 ");
                capacity = capacity - c[i];
            }
        }
    }

优化空间的动态规划

  /**
     * 动态规划优化空间
     * 只能够找出最大价值 无法获得最佳方案
     * @param n        输入规模
     * @param capacity 背包容量
     */
    public int dynamicKnapsackSR1(int n, int capacity) {
        // 枚举每一种商品
        for (int i = 1; i <= n; i++) {
            /*
             *  枚举商品的每一种可能重量从 capacity ——> 1
             *  这里必须从后往前否则会覆盖
             *  算到如f[21] 的时候 f[14] 肯定被计算过了,被新的覆盖了(本来应该是0计算过后变成24)
             *  f[21] = Math.max(24 + f[24-10] == 24, f[21] == 0);
            */

            for (int j = capacity; j >= 1; j--) {
            // for (int j = 0; j <= capacity; j++) {
                // 在容量不超出的情况下,选择下件商品使得背包的价值更大
                if (c[i] <= j) {
                    f[j] = Math.max(v[i] + f[j - c[i]], f[j]);
                }
            }
            // 输出每个商品的表
            // System.out.println(Arrays.toString(f));
        }
        return f[capacity];
    }

公共的问题初始化(测试用)

public class Knapsack {
    // 保存每个商品的体积
    private final int[] c;
    // 保存每个商品的价值
    private final int[] v;
    // 保存最优方案
    private final boolean[] plan;
    // 二维记忆数组
    private final int[][] memory;
    private final int[] f;
    // 动态记忆
    private final int[][] rec;

    /**
     * 问题初始化
     *
     * @param count    输入规模
     * @param capacity 背包容量
     */
    public Knapsack(int count, int capacity) {
        // 保存每个商品的体积 将第一位写作0方便对应真实物品下标
        c = new int[]{0, 10, 3, 4, 5, 4};
        // 保存每个商品的价值
        v = new int[]{0, 24, 2, 9, 10, 9};
        plan = new boolean[count + 1];
        memory = new int[count + 1][capacity + 1];
        f = new int[capacity + 1];
        rec = new int[count + 1][capacity + 1];
    }
 }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值