算法27:从暴力递归到动态规划(3)---背包问题——从左往右尝试模型

给定两个长度都为N的数组weightsvalues

weights[i]values[i]分别代表 i号物品的重量和价值。

给定一个正数bag表示一个载重bag的袋子,

你装的物品不能超过这个重量。

返回你能装下最多的价值是多少?

递归:

package code03.动态规划_07;

/**
 * 给定两个长度都为N的数组weights和values,
 * weights[i]和values[i]分别代表 i号物品的重量和价值。
 * 给定一个正数bag,表示一个载重bag的袋子,
 * 你装的物品不能超过这个重量。
 * 返回你能装下最多的价值是多少?
 */
public class BagMaxValue_03 {

    public static int maxValue(int[] weight, int[] value, int bag)
    {
        if (weight == null || weight.length == 0
                || value == null || value.length == 0 || bag < 0) {
            return 0;
        }
        return func(weight, value, bag, 0);
    }

    public static int func(int[] weight, int[] value, int bag, int index)
    {
        //数组已经结束了,没有货物了
        if (index == weight.length) {
            return 0;
        }

        int result1 =func(weight, value, bag, index + 1);
        int result2 = 0;
        //大于等于0,背包是能够容纳当前货物的
        if (bag - weight[index] >= 0) {
            result2 = value[index] + func(weight, value, bag-weight[index], index + 1);
        }

        return Math.max(result1,result2);
    }

    public static void main(String[] args)
    {
        int[] weight = { 3, 2, 4, 7, 3, 1, 7 };
        int[] value = { 5, 6, 3, 19, 12, 4, 2 };
        int bag = 15;

        int result = maxValue(weight, value, bag);
        System.out.println(result);
    }
}

递归 + 动态规划

package code03.动态规划_07;

/**
 * 给定两个长度都为N的数组weights和values,
 * weights[i]和values[i]分别代表 i号物品的重量和价值。
 * 给定一个正数bag,表示一个载重bag的袋子,
 * 你装的物品不能超过这个重量。
 * 返回你能装下最多的价值是多少?
 */
public class BagMaxValue_03_opt1 {

    public static int maxValue(int[] weight, int[] value, int bag)
    {
        if (weight == null || weight.length == 0
                || value == null || value.length == 0 || bag < 0) {
            return 0;
        }
        int[][] dp = new int[weight.length][bag+1];
        for (int i = 0; i < dp.length; i++) {
            for (int j = 0; j < dp[i].length; j++) {
                dp[i][j] = -1;
            }
        }
        return func(weight, value, bag, 0, dp);
    }

    public static int func(int[] weight, int[] value, int bag, int index, int[][] dp)
    {
        //数组已经结束了,没有货物了
        if (index == weight.length) {
            return 0;
        }

        if (dp[index][bag] != -1) {
            return dp[index][bag];
        }

        int result1 =func(weight, value, bag, index + 1, dp);
        int result2 = 0;
        //大于等于0,背包是能够容纳当前货物的
        if (bag - weight[index] >= 0) {
            result2 = value[index] + func(weight, value, bag-weight[index], index + 1, dp);
        }

        int maxResult = Math.max(result1,result2);
        //放入缓存
        dp[index][bag] = maxResult;
        return maxResult;
    }

    public static void main(String[] args)
    {
        int[] weight = { 3, 2, 4, 7, 3, 1, 7 };
        int[] value = { 5, 6, 3, 19, 12, 4, 2 };
        int bag = 15;

        int result = maxValue(weight, value, bag);
        System.out.println(result);
    }
}

动态规划
 

package code03.动态规划_07;

/**
 * 给定两个长度都为N的数组weights和values,
 * weights[i]和values[i]分别代表 i号物品的重量和价值。
 * 给定一个正数bag,表示一个载重bag的袋子,
 * 你装的物品不能超过这个重量。
 * 返回你能装下最多的价值是多少?
 */
public class BagMaxValue_03_opt2 {

    public static int maxValue(int[] weight, int[] value, int bag)
    {
        if (weight == null || weight.length == 0
                || value == null || value.length == 0 || bag < 0) {
            return 0;
        }

        int N = weight.length;
        int[][] dp = new int[N + 1][bag + 1];
        for (int index = N - 1; index >= 0; index--) {
            for (int rest = 0; rest <= bag; rest++) {
                //以下逻辑完全照抄递归逻辑
                int p1 = dp[index + 1][rest];
                int p2 = 0;
                int next = rest - weight[index] < 0 ? -1 : dp[index + 1][rest - weight[index]];
                if (next != -1) {
                    p2 = value[index] + next;
                }
                dp[index][rest] = Math.max(p1, p2);
            }
        }
        //为什么返回的是dp[0][bag], 也是完全照抄递归的参数。递归
        //方法给的什么值,动态规划中就返回什么值。
        return dp[0][bag];
    }

    public static void main(String[] args)
    {
        int[] weight = { 3, 2, 4, 7, 3, 1, 7 };
        int[] value = { 5, 6, 3, 19, 12, 4, 2 };
        int bag = 15;

        int result = maxValue(weight, value, bag);
        System.out.println(result);
    }
}

总结:

1. 动态规划逻辑,完全照抄递归方法内部逻辑。想要写好动态规划,一个好的递归是关键

2. 递归方法传入的参数初始值是什么,那么动态规划返回的数组下标就需要一一对应。前面写了2篇博客,细心的童鞋可以去查看

3. 动态规划的二维数组中,行对应的都是数组,而列对应的是剩余的可变参数。上一篇的对应的是剩余步数、本篇对应的是bag的剩余容量

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值