动态规划法求解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的价值。
按照以上方程,我们可以填表格,得到以下结果:
物品 容量 | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
---|---|---|---|---|---|---|---|
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
1 | 0 | 0 | 20 | 25 | 25 | 25 | 25 |
2 | 0 | 15 | 20 | 35 | 35 | 35 | 35 |
3 | 0 | 15 | 20 | 35 | 40 | 55 | 55 |
4 | 0 | 15 | 20 | 35 | 40 | 55 | 60 |
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;
}