动态数组——有限背包问题

有n 个物品,它们有各自的重量和价值,现有给定容量的背包,如何让背包里装入的物品具有最大的价值总和?

规划方向:d[i][j]表示把前i个物品装到容量为j的背包中的最大总重量

#define INF 100

#include<algorithm>
#include<iostream>
using namespace std;

int c = 10,n=3;  //c是体积
int d[INF][INF];  // maxw[s]代表此体积能装的最大重量
int v[3] = { 1,3,5 };
int w[3] = { 1,7,8 };


int main()
{
	memset(d, -INF, sizeof(d));
	int i, j;
	for (i = 0; i < n; i++) {  //d[i][j] 把前i个物品装到容量为j的背包的最大总重量
		for (j = 0; j <= c; j++) {
			d[i][j] = (i == 0 ? 0 : d[i - 1][j]);   //先不装第i个物品,还剩j容量时,等于d[i - 1][j]
			if (j >= v[i]) {
				d[i][j] = max(d[i][j], d[i - 1][j - v[i]] +w[i]);  //判断装了第i个物品会不会更大
			}
		}
	}
	cout <<"能装的最大重量为:"<< d[n-1][c] <<endl;
	return 0;
}

此种方法,打印时不太方便,不能保证字典序最小

结果

 

读入时可以边读边计算

#define INF 100

#include<algorithm>
#include<iostream>
using namespace std;

int c = 10,n=3;  //c是体积
int d[INF][INF];  // maxw[s]代表此体积能装的最大重量
//int v[3] = { 1,3,5 };
//int w[3] = { 1,7,8 };


int main()
{
	memset(d, -INF, sizeof(d));
	int i, j,v,w;
	for (i = 0; i < n; i++) {  //d[i][j] 把前i个物品装到容量为j的背包的最大总重量
		cin >> v >> w;
		for (j = 0; j <= c; j++) {
			d[i][j] = (i == 0 ? 0 : d[i - 1][j]);   //先不装第i个物品,还剩j容量时,等于d[i - 1][j]
			if (j >= v) {
				d[i][j] = max(d[i][j], d[i - 1][j - v] +w);  //判断装了第i个物品会不会更大
			}
		}
	}
	cout <<"能装的最大重量为:"<< d[n-1][c] <<endl;
	return 0;
}

结果:

 

还可以将d变成滚动数组,由二维变成一维

#include<iostream>
using namespace std;

int c = 6,n=3;  //c是体积
int d[INF];  //代表此体积能装的最大重量
//int v[3] = { 1,3,5 };
//int w[3] = { 4,9,10 };


int main()
{
	memset(d, 0, sizeof(d));
	int i, j,v,w;
	for (i = 0; i < n; i++) {  //d[i][j] 把前i个物品装到容量为j的背包的最大总重量
		cin >> v >> w;
		for (j = c; j >= 0; j--) {
			if (j >= v) {
				d[j] = max(d[j], d[j - v] +w);  //因为i递增,所以d[j]其实是d[i-1][j]已经算出的
			}  //把max(d[i-1][j],d[i-1][j-v])保存在f[j]中,覆盖掉原来的f[i-1][j]
		}
	}
	cout <<"能装的最大重量为:"<< d[c] <<endl;
	return 0;
}

结果:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值