动态规划法求解0/1背包问题

动态规划法求解0/1背包问题

题目:用动态规划法求如下0/1背包问题的最优解:有5个物品,其重量分别为 (3, 2, 1, 4, 5),物品的价值分别为 (25, 20, 15, 40, 50),背包容量为 6。写出求解过程。

解析:首先,我们可以建立一个5行7列的表格,其中行表示物品,列表示背包容量(从0到6)。对于每个物品i和每个背包容量j,我们可以计算在将物品i放入背包时可以得到的最大价值。

具体地,对于每个物品i和背包容量j,我们可以计算以下两种情况的最大值:

不将物品i放入背包,此时最大价值就是在背包容量j时不放入物品i时的最大价值,即f(i-1,j)。

将物品i放入背包,此时最大价值就是物品i的价值,加上将剩余的容量装满时的最大价值,即f(i-1,j-w[i])+v[i]。

综合以上两种情况,我们可以得到动态转移方程

f(i,j) = max{f(i-1,j), f(i-1,j-w[i])+v[i]}, 0≤j≤6, 1≤i≤5

其中,w[i]表示物品i的重量,v[i]表示物品i的价值。

按照以上方程,我们可以填表格,得到以下结果:

物品 容量0123456
00000000
1002025252525
20152035353535
30152035405555
40152035405560
5
#include<iostream>
#include<cmath>

using namespace std;

//用于记录是否存放当前地物体
int inOut[5];
//保存最多的价值
int value;
//定义背包的总共的重量的
int bagVolume = 6;

/*
	描述:背包问题的约束条件,当传入对应的序号,就去判定是否要放对应的物品
	参数:放入包中物体的序号
	返回:当前物体总重量和背包容量的关系
		 true:表示没有超重
		 false:表示超重
	原理:判定当前的物品的总重量,是不是小于物体的实际重量
*/
bool bagConstraint(int m, int weight[]) {
	//一直遍历m层之前的所有物体,求出其对应的重量
	int allweight = 0;
	for (int i = 0; i <= m; ++i)
	{
		//计算出总共的重量的
		allweight += inOut[i] * weight[i];
	}

	//比较当前的物体总重量和背包的总重量关系
	return allweight <= bagVolume;
}

/*
	描述:深度优先搜索的函数,递归函数
	参数:m:是要装入背包的物品的数量
		 weight:是背包中各个物品的重量
		 value:是背包中各个物品的价值
	返回:最终返回的是最大的价值
	问题:
*/
void bagProblem(int m, int weight[], int valueAll[]) {

	//首先确定终止条件,那就比较最大值
	if (m == 5)
	{
		int sum = 0;
		for (int i = 0; i < m; ++i)
		{
			sum += valueAll[i] * inOut[i];
		}

		//比较最大值
		if (sum > value)
		{
			value = sum;
		}
	}
	else {
		//没有到达终止条件,继续向下进行递归
		for (int i = 0; i < 2; ++i)
		{
			inOut[m] = i;
			//判定是否满足对应约束条件
			if (bagConstraint(m, weight))
			{
				//满足约束条件,继续向下进行递归的
				bagProblem(m + 1, weight, valueAll);
			}
		}

	}

}

int main(int argc, char const* argv[])
{
	cout << "物品数量:5" << endl;
	cout << "背包容量:6" << endl;
	cout << "重量分别是:3, 2, 1, 4, 5" << endl;
	cout << "价值分别是:25, 20, 15, 40, 50 " << endl;
	int num = 5;
	int weight[5] = { 3, 2, 1, 4, 5 };
	int valueAll[5] = { 25, 20, 15, 40, 50 };
	bagProblem(0, weight, valueAll);
	cout << "最终的结果是:" << value << endl;
	cout << endl;
	return 0;
}

测试结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值