回溯之详细分析0-1背包问题
题目:
给定n种物品和一个背包·物品i的重量是Wi,其价值为Vi,背包最大承载重量为C·物品是不可分割的,应如何选择装入背包的物品,使得装入背包中物品的总价值最大?
回溯的思路:
回溯法的核心思想是深度优先搜索,一般需要解空间以图或者树的形式,回溯法从根节点出发,以深度优先搜索空间树。该问题中每个物品有两种状态装与不装,求解用的是完全二叉树。深度优先搜索所有的情况最终得到最优解。
回溯
深度优先从根节点开始,首先定义当前的最大价值now_v和当前总重量now_w。如果从根节点到下一个子节点加上物品的重量后背包还有剩余,调用递归函数继续向下搜索。如果到达了最下面一层,然后进行最优价值与当前最大价值进行判断。进而获得最优解。
代码如下:
//回溯法
int LookBack(int i,int now_w,int now_v){
int j;
if(i>N){
if(now_v>mostvalue)
mostvalue=now_v;
}else{
if(now_w+w[i]<=C){
now_w+=w[i];
now_v+=v[i];
LookBack(i+1,now_w,now_v);
//从背包里取出物品进行回溯
now_w-=w[i];
now_v-=v[i];
}
LookBack(i+1,now_w,now_v);
}
return mostvalue;
}
算法分析
回溯法是通过找出二叉树中满足约束条件的所有解然后进行最优解的比较,而分支限界法通过寻找满足约束条件的一个解,或是在满足约束条件的最优解。回溯法以深度优先的方式搜索二叉树。
复杂度分析
时间复杂度:O(2^n),使用了二叉树,共有n层,需要搜索2^n个节点,所以最多需要执行2^n次。
回溯法的关键技术
二叉树的遍历搜索,关键技术是把背包里的物品取出进行回溯:now_w-=w[i];now_v-=v[i];