回溯算法

回溯算法

1.回溯算法的基础理论:

回溯法是一种组织搜索的一般技术,有“通用的解题法”之称,用它可以系统地搜索一个问题的所有解或任意解。有许多问题,当需要找出它的解集或者要求回答什么解是满足某些约束条件的最佳解时,往往要使用回溯法。可以系统地搜索一个问题的所有解或任意解,既有系统性又有跳跃性。回溯法的基本做法是搜索,或是一种组织的井井有条,能避免不必要搜索的穷举式搜索法。这种以深度优先的方式系统地搜索问题的解的方法称为回溯法。

1.1问题的解空间应用回溯法求解时,需要明确定义问题的解空间。问题的解空间应至少包含问题的一个(最解)。

定义了问题的解空间后,还应将解空间很好地组织起来,使得回溯法能更方便地搜索解空间,通常组织成树或图的形式。

1.2回溯法的基本思想

在确定了解空间的组织结构后,回溯从开始节点(根节点)出发,以深度优先的方式搜索整个解空间。这个开始节点成为一个活结点,同时成为当前的扩展结点。在当前的扩展结点,搜索向深度方向进入一个新的节点。这个新节点成为一个新的活结点,并成为当前的扩展结点。若在当前扩展结点处不能再向深度方向移动,则当前的扩展结点成为死节点,即该活结点成为死节点。此时回溯到最近的一个活结点处,并使得这个活结点成为当前的扩展结点。回溯法以这样的方式递归搜索整个解空间(树),直到满足终止条件。

使用回溯法解题包含三个步骤:
(1)针对所给问题,定义问题的空间树
(2)确定易于搜素的解空间结构
(3)以深度优先的方式搜索解空间树,并且在搜索过程中用剪枝函数避免无效搜索
1.3子集树与排列树

有时问题是要从一个集合中的所有子集中搜索一个集合,作为问题的解。或者从一个集合的排列中搜索一个排列,作为问题的解。回溯算法可以很方便地遍历一个集合的所有子集或者所有排列。当问题是要计算n个问题的子集,以便达到某个优化目标时,可以把这个解空间组织成一个子集树。例如,n个物品的0-1背包问题相应的解空间树就是一个子集树。这类子集树通常有2的n次方个叶节点。

回溯算法搜索子集树的伪代码

void Backtrack(int t) {     //t 表示当前是树的第t层,即对集合 S 中的第 t 个元素进行判断
    if (t > n)
        output(x);          //大于S中总的元素个数 ,遍历完成 
    else
        for (int i = 0; i < = l; i++) {     // 两种可能 加入或者不加入到解集合 每个节点只有两个子树
            x[t] = i;                    //即0 - 1
            if (Constraint(t) && Bound(t)){     //满足约数条件  
                    Backtrack(t + 1);           //对 t+1 层进行判断 
                } 
        }
}

回溯算法搜索排列树的伪代码:

void Backtrack(int t) {     //t 表示集合 S 的第 t 个元素 
    if (t > n)
        output(x);
    else
        for (int i = t; i <= n; i++) {      //第t 个元素与其后面的所有元素进行交换位置 
        	//为了保证排列中每个元素不同,通过交换x[t], x[i]来实现
            swap(x[t], x[i]);
            if (constraint(t) && bound(t)){ 
                    backtrack(t + 1);
                } 
            swap(x[t], x[i]);      //恢复状态
        }
}

基本应用:装载问题,0-1背包问题,图的m着色问题,n皇后问题,流水作业调度问题,子集和问题。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值