问题:
通过指定n个物品对应的重量w以及价值v,指定当前背包容量C,通过动态规划求解当前可以达到的最大价值以及如何装可以达到该最大价值。如:
C=23kg
商品序号 | 1 | 2 | 3 | 4 | ….. |
重量 | 10kg | 5kg | 2kg | 7kg | 4kg |
价值 | 80元 | 50元 | 10元 | 35元 | 24元 |
如何取得到最大价值?X[i]的取值?
③对上述算法进行时间复杂性分析,并输出程序运行时间及运行结果。
算法原理:
理解0/1背包问题的目标函数及约束函数。能够根据动态规划思想,进行0/1背包最优子结构性质分析、子结构递归关系构建、编码实现子结构最优值求解以及最优解构造。
解题思路:
首先定义一些变量:P表示物品的价值,W表示第 i 个物品重量,定义Pk:当前背包容量 j,前 i 个物品最佳组合对应的价值,同时背包问题抽象化(X1,X2,…,Xn,其中图中v操作表示选择,x操作表示不选)。步骤如下:1、建立模型,2、寻找约束条件,3寻找递推关系式,这步尤为关键,4填表找出最优解。下面我举个例子分析。
代码实现:
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
int f[6][23]={0};
int w[6]={0,10,5,2,7,4};//第n件物品的重量
int v[6]={0,80,50,10,35,24};//第n件物品的价值
int main()
{
int i,j;
memset(f,0,sizeof(f));
for(int i=1;i<6;i++)
for(int j=1;j<23;j++)
{
if(w[i]>j)
f[i][j]=f[i-1][j];
else
f[i][j]=max(f[i-1][j-w[i]]+v[i],f[i-1][j]);
}
for (int i=0;i<6;i++)
for(int j=0;j<9;j++)
printf("f[%d][%d]=%d\n",i,j,f[i][j]);
}
其中关键部分是递归方程,其是算法的核心,分两种情况考虑,第一种是第k件物品不放在背包中的情况,第二种是当第k件物品的重量不大于背包剩余的容量时,意味着第k件物品可以放置在背包中,“可以放置”并不意味着一定要放在背包中吧,所以,存在两种情形,第k件物品放在背包中或者第k件物品不放在背包中。
实验记录:
第一种情况
此时结果:
第二种情况:
结果如下
六、思考与总结
0-1背包问题是背包问题的延申,利用动态规划思想求解是比较快的,寻找递归关系,通过填表方式把子问题记录下了,最后找到最优解。在0-1背包问题中关键就是寻找递归方程,摸清他们的关系。这里我就分两种情况来看,第一种是第k件物品不放在背包中的情况,第二种是当第k件物品的重量不大于背包剩余的容量时,意味着第k件物品可以放置在背包中,“可以放置”并不意味着一定要放在背包中吧,所以,存在两种情形,第k件物品放在背包中或者第k件物品不放在背包中。搞清楚这点问题就简单了,最后使用回溯,轻松输出。