1、搜索与回溯

 

一、课程目标

  1. 搜索的概念
  2. 回溯的作用
  3. 算法的要素
  4. 案例
  5. 基本模型

二、目标详解

1、搜索的概念

我们学过枚举算法:穷举所有的状态,进行判定,获得解。

然而有些问题的状态比较特殊,是由多个维度组成,比如百钱买百鸡,状态是公鸡数x、母鸡数y、小鸡数z的组合,那么这些状态如何穷举呢?

如果维度不多,可以用多重循环实现,当维度比较多或者个数不确定的时候,就需要用到搜索算法了。

搜索算法利用递归函数来获得所有的维度组合,进而筛选出需要的状态,进行判定求解。

2、回溯

搜索时,当某个状态明显不满足,就可以退回上一个状态,继续选择别的方向。这种思想就称为回溯。

假设每一步的状态为Xi,某一个解(由状态组成的路径)为X1 .. Xn。

使用回溯法的前提:

  • 如果X1..Xn成立,则X1..Xn-1肯定也成立。
  • 如果X1..Xn不成立,则X1..Xn+1肯定也不成立。

3、搜索算法的要素

搜索算法往往采用递归函数的方式来实现搜索+回溯,实际如果熟练掌握算法的要素的话,也可以采用栈、死循环等方式来实现。

3.1 退出

如果把搜索算法看成很多层选择的话,那么当每一层的选择(路径)都走完以后,就可以退出了。

退出条件:

  • 栈结构实现:栈里没有节点,就退出。
  • 递归函数实现:第一层函数调用结束,自然退出。相当于栈里没有节点了。
  • 死循环实现:从第一层开始搜索,每层搜索结束,回退一层,到第0层就表示退出。

3.2 求解

最后一层有可行路径,表示有了一个解(从第一层到最后一层的路径)。

一般每一层有可行路径后,即进入下一层搜索,如果下一层超过了层数就表示有解。

3.3 选择

每层根据可选的路径进行选择,根据某种判定条件检查路径是否可行,如果可行就进入下一层搜索。

如果所有选择都不可行(表示无解)则回退到上一层。

3.4 回溯

  • 当进入下一层前,记录本层的选择,一方面可能下一层的判定要用到,另一方面求解时用到。
  • 当求解完成回退,或某层无解回退时,需要把上一层的记录清除,以便上一层再往下选择。

4、案例

以1-3的全排列为例子,如下图:

  • 第一轮:
    • 第一层1..3中选择了1
    • 然后调用第二层1..3中选择了2(1已经被第一层选择)
    • 然后调用第三层1..3中选择了3(1,2已经被选)
    • 解为1 2 3,然后回溯到第三层
    • 第三层已经没有可选,继续回溯到第二层
    • 第二层还有3可以选择,因此作为第二轮的开始
  • 第二轮:
    • 第一层不变,从第二轮开始
    • 第二轮选择3
    • 然后调用第三层1..3中选择2(1, 3已经被选)
    • 解为1 3 2,然后回溯到第三层
    • 第三层已经没有可选,继续回溯到第二层
    • 第二层已经没有可选,继续回溯到第一层
    • 第一层还有2、3可选,因此作为第三轮的开始
  • 第三轮…依次类推

5、基本模型

void search() {
  if(有解) {
    处理解
    返回;
  }

  for(本层可行的选择) {
    状态变化;
    search();//往下递归搜索
    回溯;
  }
}

四、扩展理解

1、递归与搜索

一般搜索会使用递归进行回溯,要注意,搜索的重点是回溯而不是递归。

搜索的每一次递归迭代代表一层方向的选择,一般是用循环来实现。比如1-3全排列里面,第一次递归代表第一个位置的选择(有3个),然后递归下去,代表第一层选择确定的情况下,第二层的选择(也有3个),以此类推。

对应的,当某层选择不可行(或已到最后)时,回溯到上一层,需要清除掉上一层的记录。

对比搜索递归与分治递归,会发现区别就在于有没有回溯。

为什么要回溯?就是因为上一层还要再看看别的方向选择。

2、解空间树

使用回溯法解题时,如果把每层搜索的状态按照树的结构连接起来,就会组成一个解空间树。树的一条边(从根到叶子)就是一个解,常见的解空间树一般可分为为排列树和子集树。

2.1 排列树

当问题为寻求n个元素的某种排列时,解空间树称为排列树,排列树通常有n!个叶子节点(第一层有n个选择,第二层n-1,依次类推)。

2.2 子集树

当问题为在n个元素的集合种找某种子集时,解空间树称为子集树。子集树实际就是满二叉树,叶子节点为为2^n个。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值