Bootstrap

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

题目:现在有四个物品,背包总容量为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
;