0-1背包回溯算法【适合小白,带分析+注释】
题目:用回溯算法实现0-1背包,背包的容积为7
装4件物品,物品的价值分别9,10,7,4,物品的重量分别是3,5,2,1,请用回溯法实现背包所能装入的最大价值?
分析:
所谓0-1背包,为了最大的价值,考虑当前物品装或者不装【只有这两种情况,而背包问题可以只装物品的部分】,解空间可以用子集数来表示。
解0-1背包问题的回溯法,与装载问题的回溯法类似,搜索解空间树时,只要左孩子结点是一个可行结点,搜索就进入左子树,而只有在右子树包含更优解时才进入右子树,否则就把右子树剪掉。
这就是问题的关键,怎么把右子树剪掉:我们可以设计一个上界函数,只有当上界函数返回的值大于当前最优值,才进入右子树(也就是说,当前这个物品我不装,而去装下一个物品,得到的价值更大)
上界函数:将物品按单位重量价值降序排列,依次取物品装入【这是为了得到一个上界值,其实本身是不能取到的,所以当物品放不下,我们可以取部分装,这就类似背包问题】
所以物品的价值,重量,单位价值属性用结构体存储,本方法大部分处理时间在这个,其实回溯很简单,主要是为了oj提交,直接根据题目所给的数据进行编程,如果只是想练习回溯,可以自己事前计算好物品的单位重量价值,然后将价值数组,重量数组也按物品的单位重量价值降序排列
//1右子树可能包含最优解才进入右子树 否则将右子树减去
//2设置r是当前剩余价值总和 cp是当前价值 bestp当前最优价值
//3上界函数 将物品但单位价值降序排列 按背包问题(可以装部分) 计算出上界值
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
#define N 4
struct node{//建立节点数组
int p;//价值
int w;//重量
double per;//平均价值
}s[N];
int P[4]