0-1背包问题

0-1背包指的当往背包里装物品是,要么装,要么不装,而不能装物品的一部分;

部分背包问题指的是可以装物品的一部分,而不必做出0-1的二分选择;

贪心算法的关键所在是(贪心选择性质和最优子结构);自上而下,一个一个的做出贪心选择,不断将问题规约到更小的子问题;

动态规划的关键所在是(重叠子问题和最优子结构);自下而上,每一步都要做出选择,但这些选择依赖于子问题的解;

题目:

总共有3件物品,背包可容纳5磅的东西,物品1重1磅价值60元,物品2重2磅,价值100元,物品3重3磅,价值为120元,怎么才能最大化背包所装物品的价值?

我们假设:c[i]是第i件物品的重量,w[i]是第i件物品的价值,f[i][j]表示背包总的重量为j时,可选物品为物品1~i,背包能获得的最大价值。

用动态规划解0-1背包问题,我么从最小子问题开始求解,直到达到原问题的规模。最小子问题,我们知道,当背包大小为0时,或者物品件数为0时,这时程序结束。所以,这些都是最小的子问题。下面来求出递推公式,并给出dp表(存储小问题的解,防止在计算大问题时带来的重复计算的时间开销)。

1、最终的递推公式如下:


根据递推公式填写的dp表格如下:

1、根据最小问题,我们进行逐个的状态转移。当物品个数为0时,那么获得的最大价值不论背包有多大,那么都为0,这就填写了第1行;同理,当背包的大小为0时,那么不论物品有多重,那么最终获得的价值为0,这就填写了第1列;

2、如果此时只放第1件物品,那么当背包的最大重量为1时,其获得的最大价值为60,同理,当为2,3...5时,均为60,因为只有一个物品;这就填写了第2行;

3、当要放2件物品时,我们要判断背包的大小是否能容纳的下2件物品;即第2件物品放还是不放。即有当j<c[2]时,那么表示物品2的大小大于背包的大小,肯定不能放,所以,当背包大小为1时,获得的最大价值为60,当背包的大小为2时,此时,因为物品2的大小等于背包的重量。此时,如果放物品2获得的价值和不放物品2获得的价值我们取最大值。同理,当背包大小为3时,到底放不放物品2?根据公式,如果不放,那么获得的最大值为60.如果放的话,因为此时背包重量为3,如果放的话最大为160;以下以此类推,最终将问题转化为:

1、如果不放第i件物品,则问题转化为前i-1件物品放入容量为j的背包中;

2、如果放入第i件物品,则问题转化为前i-1件放入剩余的容量为j-c[i]的背包中,此时能获得的最大价值为f[i-1][j-c]i]]+w[i]。

#include<iostream>
#include<algorithm>
using namespace std;
int main(){
	int N = 3, V = 5;//N为物品数量,V为背包的容量
	int c[4] = { 0, 1, 2, 3 };
	int w[4] = { 0, 60, 100, 120 };
/*	int **dp = new int *[N + 1];
	for (int i = 0; i < N + 1; i++){
		dp[i] = new int[V + 1];
	}*/
	int(*dp)[6] = new int[4][6];
	//填dp表
	for (int i = 1; i < N + 1; i++){
		dp[i][0] = 0;
	}
	for (int j = 1; j < V + 1; j++){
		dp[0][j] = 0;
	}
	dp[0][0] = 0;
	for (int i = 1; i < N + 1;i++)
	{
		for (int j = 1; j < V + 1; j++){
			if (j < c[j]){
				dp[i][j] = dp[i - 1][j];
			}
			else{
				dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - c[i]] + w[i]);
			}
		}
	}
	int result = dp[3][5];
	cout << result << endl;
// 	for (int i = 0; i < 4; i++){
// 		delete[]dp[i];
// 	}
	delete []dp;
	return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值