简单背包问题详解——炼码92 · 背包问题

目录

题目

解析

暴力解法

动态规划解法

递推公式

dp数组初始化

遍历顺序

代码


题目

描述

在 n 个物品中挑选若干物品装入背包,最多能装多满?假设背包的大小为m,每个物品的大小为AiAi​
(每个物品只能选择一次且物品大小均为正整数)

样例

样例 1:

输入:

数组 = [3,4,8,5]
backpack size = 10

输出:

9

解释:

装4和5.

样例 2:

输入:

数组 = [2,3,5,7]
backpack size = 12

输出:

12

解释:

装5和7.

解析

暴力解法

首先先思考这道题的一个暴力解法,对于一个物品,它只有取或者不去两种可能,这样进行dfs进行递归,记录下每种情况的最大值,总的时间复杂度就为2的n次方。

动态规划解法

然后我们再思考如何使用dp动态规划来解决这道题目。

递推公式

dp[i][j]

表示的是下标为0到i的物品任取然后放进容量为j的背包里总的价值

不放物品i表示的最大价值为dp[i-1][j]

放物品i则为dp[i - 1][j - weight[i]] + value[j]

所以递推公式为:dp[i][j] = max(dp[i-1][j],dp[i - 1][j - weight[i]] + value[j])

dp数组初始化

由递推公式可知,当前数组的值是由它上面和它左上角的元素推导出来的

首先初始化第一列,因为背包总容量为0,所以一个物品都装不了,总价值为0,所以第一列的值都为0

对于第一行,只能装物品0,如果容量大于物品0的重量就装,否则就为0

遍历顺序

一般默认是先遍历物品,再遍历背包,两重for循环

但对于二维dp来说,先遍历背包容量,再遍历物品也是OK的,因为dp是由它上面那个元素和它左上角的元素得到的,无论是按行逐行遍历,还是按列逐列遍历,都可以得到正确的dp数组。

代码

初始化行和列,然后推导dp数组时进行判断如果j>=a[i]再进行max进行推导。

class Solution {
public:
    /**
     * @param m: An integer m denotes the size of a backpack
     * @param a: Given n items with size A[i]
     * @return: The maximum size
     */
    int backPack(int m, vector<int> &a) {
        // write your code here
        if(a.size() == 0 || m == 0)
            return 0;
        //如果背包没容量或者没物品,最大值肯定为0
        //就不用动态规划了
        int n = a.size();
        const int N = 1e5 + 10;
        int dp[1010][N];
        //初始化dp数组的行和列
        //横坐标为物品编号,纵坐标为背包容量
        for(int j = 0; j <= m; j++) {
            if(j >= a[0])
                dp[0][j] = a[0];
            else
                dp[0][j] = 0;
        }
        for(int i = 0; i < n; i++)
            dp[i][0] = 0;
            //没容量,一个物品都装不了,总价值肯定为0

        for(int i = 1; i < n; i++) {
            for(int j = 0; j <= m; j++) {
                if(j >= a[i])
                    dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - a[i]] + a[i]);
                else
                    dp[i][j] = dp[i - 1][j];
            }
        }

        return dp[a.size() - 1][m];
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

柏箱

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值