动态规划-背包问题

一、题目描述

有 n 个物品和一个大小为 m 的背包. 给定数组 A 表示每个物品的大小和数组 V表示每个物品的价值,问最多能装入背包的总价值是多大?

样例

样例 1:

输入: m = 10, A = [2, 3, 5, 7], V = [1, 5, 2, 4]
输出: 9
解释: 装入 A[1] 和 A[3] 可以得到最大价值, V[1] + V[3] = 9 

样例 2:

输入: m = 10, A = [2, 3, 8], V = [2, 5, 8]
输出: 10
解释: 装入 A[0] 和 A[2] 可以得到最大价值, V[0] + V[2] = 10

挑战

O(nm) 空间复杂度可以通过, 不过你可以尝试 O(m) 空间复杂度吗?

注意事项

  1. A[i], V[i], n, m 均为整数
  2. 你不能将物品进行切分
  3. 你所挑选的要装入背包的物品的总大小不能超过 m
  4. 每个物品只能取一次

二、解法

F(i, j): 前i个物品放入大小为j的背包中所获得的最大价值

状态递推:对于第i个商品,有一种例外,装不下,两种选择,放或者不放

如果装不下:此时的价值与前i-1个的价值是一样的 F(i,j) = F(i-1,j)

如果可以装入:需要在两种选择中找最大的

F(i, j) = max{F(i-1,j), F(i-1, j - A[i]) + V[i]}

F(i-1,j): 表示不把第i个物品放入背包中, 所以它的价值就是前i-1个物品放入大小为j的背包的最大价值

F(i-1, j - A[i]) + V[i]:表示把第i个物品放入背包中,价值增加V[i],但是需要腾出j - A[i]的大小放 第i个商品

初始化:第0行和第0列都为0,表示没有装物品时的价值都为0 F(0,j) = F(i,0) = 0

返回值:F(n,m)

三、代码

class Solution {
public:
    /**
     * @param m: An integer m denotes the size of a backpack
     * @param A: Given n items with size A[i]
     * @param V: Given n items with value V[i]
     * @return: The maximum value
     */
    int backPackII(int m, vector<int> &A, vector<int> &V) {
        // write your code here
                // write your code here
        if (A.empty() || V.empty() || m < 1) 
			return 0;
			
		const int N = A.size() + 1;
		const int M = m + 1;
		std::vector<std::vector<int> > result;
		result.resize(N);

		for (auto & e : result) 
		    e.resize(M, 0);
		
		for (int i = 1; i < N; ++i) 
		{
			for (int j = 1; j != M; ++j) 
			{
				if (A[i - 1] > j) 
					result[i][j] = result[i - 1][j];
				else
				{
					int newValue = result[i-1][j-A[i-1]] + V[i - 1];
					result[i][j] = max(newValue, result[i - 1][j]);
				}
			}
		}
		return result[N - 1][m];
    }
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值