(01背包型动态规划)lintcode125背包问题(二)

题目

描述
有 n 个物品和一个大小为 m 的背包. 给定数组 A 表示每个物品的大小和数组 V 表示每个物品的价值.

问最多能装入背包的总价值是多大?

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

样例

样例 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

分析

题目中指定每个物品只能拿一次且不能将物品分割,所以这道题是一道01背包动态规划

首先要确定最后一步

f[n],[m] (n是物品的数量,m为背包的容量),它的前一个状态f[n-1],[m]就是拿n-1个物品的状态,而最后一步只有两个选择,如果f[n-1],[m]已经达到了最大值,那最后一件物品就不需要拿了,反之就需要拿。

转移方程

f[n],[m]=max(f[n-1],[m] f[n-1],[m-最后一件物品]+最后一件物品的价值 )条件:m>=物品重量&&f[n-1],[m-最后一件物品]可以拼的出来

开始写代码

1.处理初始化

创建表示状态的二维数组

		vector<vector<int> > f(len+1,vector<int>(m+1));

初始化数组的第一个元素以及第一行,第一个0,0的状态是0件物品要求容量0,那这个状态的值就是0,然后就是(0,1),(0,2)…(0,m)分别代表物品为0个时,拼出重量为1,2,3…m的最大价值,当然是拼不出来,这里用-1来表示拼不出来

		f[0][0]=0;		//当拿0个物品时
		for(int i=1;i<=m;i++)
			f[0][i]=-1;
2.转移方程

接下来就是核心,转移方程创建二层循环,外层的循环代表物品的数量,内层代表背包的容量,值代表最大价值,-1代表拼不出来当前重量

		for(int i=1;i<=len;i++)		//动规核心 
		{
			for(int j=0;j<=m;j++)
			{
				f[i][j]=f[i-1][j];		//初始化

				if(j>=A[i-1]&&f[i-1][j-A[i-1]]!=-1)
				{
					f[i][j]=max(f[i][j],f[i-1][j-A[i-1]]+V[i-1]);
				} 	
			
			}
		}
3.找出最大价值并返回

这个时候最可能犯的错误就是直接返回f[n],[m],但是背包装的重量最大不一定价值就是最大的,所以应该在最后一行中找出一个最大值

		int ans=0;
		for(int i=0;i<=m;i++)
			ans=max(ans,f[len][i]);

完整代码

class Solution {
public:
   
    int backPackII(int m, vector<int> &A, vector<int> &V) {
        int len=A.size();
        
		vector<vector<int> > f(len+1,vector<int>(m+1));
		
		f[0][0]=0;		//当拿0个物品时
		for(int i=1;i<=m;i++)
			f[0][i]=-1;
		
		 
		for(int i=1;i<=len;i++)		//动规核心 
		{
			for(int j=0;j<=m;j++)
			{
				f[i][j]=f[i-1][j];		//初始化

				if(j>=A[i-1]&&f[i-1][j-A[i-1]]!=-1)
				{
					f[i][j]=max(f[i][j],f[i-1][j-A[i-1]]+V[i-1]);
				} 	
			
			}
		}
		
		int ans=0;
		for(int i=0;i<=m;i++)
			ans=max(ans,f[len][i]);
			
		return ans;
    }
};
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

White boy&

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

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

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

打赏作者

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

抵扣说明:

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

余额充值