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叉树

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背包问题的回溯法中,剪枝用的上界函数问题的主要内容,如果未能解决你的问题,请参考以下文章

0-1背包问题的回溯法代码

0-1背包-回溯法

回溯求解0-1背包

动态规划 0-1背包问题

动态规划中的0-1背包问题怎么去理解?要求给出具体实例和详细步骤。。。

用回溯法做0-1背包问题,这两行(程序中标注)是干嘛?为啥又要减?