动态规划(6):完全背包问题

一、问题描述:

给定一组物品,给出每种物品的价值和重量,每种物品足够多,在限定重量内,如何选择,才能使物品总价值最高

二、解决方案:

设 f ( x ) 表 示 重 量 不 超 过 x 千 克 的 最 大 价 值 , 则 : 设f(x)表示重量不超过x千克的最大价值,则: f(x)x
f ( x ) = m a x { f ( x − w e i g h t [ i ] ) + v a l u e [ i ] } f(x) = max\{f(x - weight[i]) + value[i]\} f(x)=max{f(xweight[i])+value[i]}
( x ≥ w e i g h t [ i ] , 1 ≤ i ≤ n ) (x \geq weight[i],1 \leq i \leq n) (xweight[i],1in)

三、代码:

// TSWorld
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>

using namespace std;

const long long MAXX = 1000;

int main()
{
	int M = 0,N = 0;
	int weight[MAXX] = {0},value[MAXX] = {0};
	int f[MAXX] = {0};

	cin>>N>>M;
	for(int i = 1;i <= N;i++)
		cin>>weight[i]>>value[i];

	for(int i = 1;i <= M;i++) {
		for(int j = 1;j <= N;j++) {
			if(i >= weight[j]) {
				f[i] = max(f[i-weight[j]]+value[j],f[i]);
			}
		}
	}

	cout<<f[M]<<endl;
	return 0;
}

四、完全背包算法优化:

4.1 思路分析:

可以用一个数组 f [ m ] f[m] f[m]来解决,数组下标表示包的最大承重, f [ m ] f[m] f[m]数值表示该承重下放的最大价值。可以代替 w e i g h t [ N ] weight[N] weight[N] v a l u e [ N ] value[N] value[N]数组,时间复杂度未优化。
动态转移方程:
f ( x ) = m a x ( f ( x − w e i g h t ) + v a l u e , f ( x ) ) f(x) = max(f(x - weight) + value,f(x)) f(x)=max(f(xweight)+value,f(x))
显然只要M足够大,就可以放无限个该物品

4.2 代码:
// TSWorld
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>

using namespace std;
const long long MAXX = 1000;

int main()
{
	int M = 0,N = 0;
	int weight = 0,value = 0;
	int f[MAXX] = {0};

	cin>>N>>M;
	
	for(int i = 1;i <= N;i++) {
		cin>>weight>>value;
		for(int j = weight;j <= M;j++) 
			f[j] = max(f[j-weight] + value,f[j]);
	}

	cout<<f[M]<<endl;
	return 0;
}

五、0/1背包算法的优化:

5.1 思路分析:
搜索方向从后向前,每次计算都会用到小于当前下标的数据,所以即使后边的下标放入该物品,前面的下标并没有放置,因此计算出来的数据每个物品最多只能放一个,也就是所谓的0/1背包问题。显然,该代码与前面代码几乎完全一致,只是一个是从前向后计算,一个是从后向前计算,但是无论是时间复杂度,空间复杂度,程序复杂度和记忆复杂度均优于最初算法。
5.2 代码:
// TSWorld
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>

using namespace std;

const long long MAXX = 1000;

int main()
{
	int M = 0,N = 0;
	int weight = 0,value = 0;
	int f[MAXX] = {0};

	cin>>N>>M;
	
	for(int i = 1;i <= N;i++) {
		cin>>weight>>value;
		for(int j = M;j >= weight;j--) 
			f[j] = max(f[j-weight] + value,f[j]);
	}

	cout<<f[M]<<endl;
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值