背包问题(力扣经典问题)

这是一篇关于背包问题的解析,通过一个四物品的例子介绍了动态规划的解题思路。文章讨论了如何在背包容量限制下,找到能放入背包的物品组合以达到最大价值,并扩展到物品有主件和附件的情况,分析了不同购买选择对最大价值的影响。此外,还提到了寻找和等于给定目标值的最长连续子数组的问题。
摘要由CSDN通过智能技术生成

题目:现在有四个物品,背包总容量为8,背包最多能装入价值为多少的物品?

物品编号 1 2 3 4
物品体积 2 3 4 5
物品价值 3 4 5 6

解法:
一、如果装不下当前物品,那么前n个物品的最佳组合和前n-1个物品的最佳组合是一样的。
二、如果装得下当前物品
假设1:装当前物品,在给当前物品预留了相应空间的情况下,前n-1个物品的最佳组合+当前物品的价值就是总价值。
假设2:不装当前物品,前n个物品的最佳组合和前n-1个物品的最佳组合是一样的。
选取假设1和假设2中较大的价值,为当前最佳组合的价值

升级:在使得背包内总价值最大的情况下,背包内装了哪些物品?
解法:从表的右下角开始回溯,如果发现前n个物品的最佳组合和前n-1个物品的最佳组合一样,说明第n个物品没有被装入;否则,第n个物品被装入

/*
v:物品种类数量
w[]:重量数组
v[]:价值数组
c:背包总容量
int[] object = new int[v]:存放的哪些物品
*/
void dynamic() {
   	//动态规划找到其下最大价值
	for(int i = 1; i <= v; i++){
   
		for(int j = 1; i <= c; j++){
   
			if(w[i] > j)
				dp[i][j] = dp[i-1][j];
			else
				dp[i][j] = Math.max(dp[i-1][j], dp[i-1][j-w[i]]+v[i]);
		}
	}
}

void Find(int i, int j) {
   	//回溯找到背包内价值最大时,有哪些物品
	if(i == 0) {
   
		for(int j = 0; j < v; j++)
			System.out.println(object[i]);//i表示物品编号;object[i]表示背包内是否有该物品
		return;
	}
	if(dp[i][j] = dp[i-1][j]) {
   
		object[i] = 0;
		Find(i-1, j);
	}
	else if(dp[i][j] == dp[i-1][j], dp[i-1][j-w[i]]+v[i]) {
   
		object[i] = 1;
		Find(i-1, j-w[i]);
	}
}

更新:

在这里插入图片描述
在这里插入图片描述
这是一道经典的动态规划问题,解题思路和上面背包问题思路一样
我们定义动规数组f[i][j]来表示前i件物品,容量为j时的最大价值,则
在这里插入图片描述

在本题中进行了一项变动,即物品分为主件和附件,考虑到一个主件最多可以购买两个附件,那我们可以细化分析,将是否购买该物品,细化为是否购买该物品,以及是否购买该物品的附件,即5种情况,不购买该物品,购买该物品,购买该物品及附件1,购买该物品及附件2,购买该物品及附件1及附件2,f[i][j]取这五种情况的最大值,这五种情况分别对应于

f[i−1][j]f[i-1][j]f[i−1][j],

f[i−1][j−w[i]]+v[i]f[i-1][j-w[i]]+v[i]f[i−1][j−w[i]]+v[i],

f[i][j]=max(f[i−1][j],f[i−1][j−w[i]−w[a1]]+v[i]+v[a1])f[i][j]=max(f[i-1][j], f[i-1][j-w[i]-w[a_1]]+v[i]+v[a_1])f[i][j]=max(f[i−1][j],f[i−1][j−w[i]−w[a1​]]+v[i]+v[a1​]),

f[i][j]=max(f[i−1][j],f[i−1][j−w[i]−w[a2]]+v[i]+v[a2])f[i][j]=max(f[i-1][j], f[i-1][j-w[i]-w[a_2]]+v[i]+v[a_2])f[i][j]=max(f[i−1][j],f[i−1][j−w[i]−w[a2​]]+v[i]+v[a2​]),

f[i][j]=max(f[i−1][j],f[i−1][j−w[i]−w[a1]−w[a2]]+v[i]+v[a1]+v[a2])f[i][j]=max
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值