0-1背包问题的回溯法中,剪枝用的上界函数问题
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了0-1背包问题的回溯法中,剪枝用的上界函数问题相关的知识,希望对你有一定的参考价值。
0-1背包问题的回溯法中,上界函数为什么用单位价值贪心来求,而不是(当前价值+剩余价值<=当前最优值) 时剪去右子树。
参考技术A 不知道你哪里看的代码,01背包的分支限界法一般有2种剪枝1、当去了i后体积超过背包容量,那么剪去该子树,体积都超了价值再大也没用。
2、当前价值+i子树中所有物品的价值<=记录的最优值,应该就是你说的把。
按单位价值贪心虽然不知道你具体指什么,我的理解是i的单位价值很低就剪了,这应该是不对的,万一i后面有个单位价值很高的怎么办。
另外,01背包哪有人会用回溯法啊,这是多么没有效率的算法啊,虽然有剪枝,但时间复杂度还是指数级的啊,你想想如果有10件物品的话,你的叶节点就有1024个了,如果100件的话,我。。。。。。!!追答
楼主你仔细看bound这个函数了么,他不就是你说的这个剪枝嘛,汗一个!
给你解释一下把,
Backtrack(int k, int cv, int rc) //k 当前取的物品编号,cv已经取到的价值,rc剩余容量,我习惯叫容量,他那里叫重量。
Bound(int i, double v, int c)//参数含义跟上面一致,在具体分析一下这个函数
double Bound(int i, double v, int c)//这边其实就是在取子树中物品的价值,只不过他是进行了按单位价值排序后来取,楼主仔细想想i子树是一个二叉树把,每件物品都有取和不取把,这边都取,只不过取的方式不一样,他按排序过的来取是吧
while (i <= n && goods[i].w <= c) //这边我取的物品总不能超过剩余容量把
v += goods[i].v;//如果取那么加上他的价值
c -= goods[i].w;//如果取那么剪去剩余容量
i++;
if (i <= n)
v += (goods[i].vw * c); //单位价值*背包剩余容量,这边我都不想吐槽了,他竟然在分割物品,这就不叫01背包了, 01背包一件物品只能取或不取,不能切割。
return v;
我很负责任的告诉你,这边的代码是很有问题的,整个算法思想是很混乱的。首先先撇开我上面说的回溯糟糕的时间复杂度不谈,这边他就没有搞清楚他的物品到底能不能切割。
(啥,字数超出限制,汗,楼主要不你在追问一下)
本回答被提问者采纳算法设计与分析——回溯法算法模板
以深度优先方式系统搜索问题解的算法称为回溯法。在回溯法中,解空间树主要分为了四种子集树、排列树、n叉树和不确定树。
在《算法设计与分析课本》中介绍了11个回溯法的问题样例,这里根据解空间树的类型做一个分类。
子集树
装载问题
0-1背包问题
算法模板:
void backtrack(int t) { if(搜索到叶子结点) { return; } for(i=0; i<=1; i++) //01二叉树 { if(满足约束函数和限界函数)//剪枝 { backtrack(t+1); } } }
排列树
旅行售货员问题
圆排列问题
电路板排列问题
算法模板:
void backtrack(int t) { if(搜索到叶子结点) { return; } for(i=0; i<=n; i++) { if(满足约束函数和限界函数)//剪枝 { swap(x[t],x[i]); backtrack(t+1); swap(x[t],x[i]); } } }
n叉树
图的m着色问题
算法模板:
void backtrack(int t) { if(搜索到叶子结点) { return; } for(i=1; i<=n; i++) //n叉树 { x[t]=i;//例如n后问题中,记录第t后所在的第i列 if(满足约束函数和限界函数)//剪枝 { backtrack(t+1); } } }
不确定树
连续邮资问题
算法模板:
void backtrack(int t) { if(搜索到叶子结点) { return; } for(i=x; i<=y; i++) //x与y由相应的函数得到 { x[t]=i; if(满足约束函数和限界函数)//剪枝 { backtrack(t+1); } } }
以上是关于0-1背包问题的回溯法中,剪枝用的上界函数问题的主要内容,如果未能解决你的问题,请参考以下文章