zoukankan      html  css  js  c++  java
  • 2018.4.24 回溯法

    为了描述问题的某一状态,必须用到该状态的上一状态,而描述上一状态,又必须用到上一状态的上一状态……这种用自已来定义自己的方法,称为递归。

    从问题的某一种可能出发, 搜索从这种情况出发所能达到的所有可能, 当这一条路走到” 尽头 “的时候, 再倒回出发点, 从另一个可能出发, 继续搜索. 这种不断” 回溯 “寻找解的方法, 称为回溯。

    回溯法是以深度优先方式系统搜索问题解的算法,适用于解决组合数较大的问题。

    回溯就是让计算机自动的去搜索,碰到符合的情况就结束或者保存起来,在一条路径上走到尽头也不能找出解,就回到原来的岔路口,选择一条以前没有走过的路继续探测,直到找到解或者走完所有路径为止。

    回溯就是一种试探,类似于穷举,但回溯有“剪枝”功能。

    回溯法一般有两种实现方式,分别是递归回溯和迭代回溯。

    回溯一般使用递归来实现,那个这个递归调用该如何来写呢?进行回溯搜索都会有一系列的步骤,每一步都会进行一些查找。而每一步的情况除了输入会不一样之外,其他的情况都是一致的。这就刚好满足了递归调用的需求。通过把递归结束的条件设置到搜索的最后一步,就可以借用递归的特性来回溯了。

    回溯常用模板:

    1.非递归模板:

       1: int a[n],i;
       2: 初始化数组a[];
       3: i = 1;
       4: while (i>0(有路可走)   and  (未达到目标))  // 还未回溯到头
       5: {
       6:     if(i > n)                                              // 搜索到叶结点
       7:     {   
       8:           搜索到一个解,输出;
       9:     }
      10:     else                                                   // 处理第i个元素
      11:     { 
      12:           a[i]第一个可能的值;
      13:           while(a[i]在不满足约束条件且在搜索空间内)
      14:           {
      15:               a[i]下一个可能的值;
      16:           }
      17:           if(a[i]在搜索空间内)
      18:          {
      19:               标识占用的资源;
      20:               i = i+1;                              // 扩展下一个结点
      21:          }
      22:          else 
      23:          {
      24:               清理所占的状态空间;            // 回溯
      25:               i = i –1; 
      26:          }
      27: }

    2.递归模板:

    1: int a[n];
       2: try(int i)
       3: {
       4:     if(i>n)
       5:        输出结果;
       6:     else
       7:     {
       8:         for(j = 下界; j <= 上界; j=j+1)  // 枚举i所有可能的路径
       9:         {
      10:             if(fun(j))                 // 满足限界函数和约束条件
      11:              {
      12:                   a[i] = j;
      13:                   ...                         // 其他操作
      14:                   try(i+1);
      15:                   回溯前的清理工作(如a[i]置空值等);
      16:              }
      17:         }
      18:      }
      19: }

    3.迭代回溯伪代码:

    void IterativeBacktrack(void){
         int t = 1;
         while(t > 0){
             if(f(n,t) < g(n,t)){
                 for(int i = f(n,t); i <= g(n,t); ++i){//这个for 是遍历各个值的意思,实际中写成for循环会有逻辑错误
                     x[t] = h(i);
                     if(constraint(t) && bound(t)){
                         if(solution(t)) Output(x);//solution 判断是否已经得到问题的解
                         else t++;
                     }
                     else t--;
                 }
             }
         }
     }

    4.递归回溯伪代码:

    void Backtrack(int t){
        if(t > n) 
            Output(x);//Output 记录或者输出可行解
        else{
            //f(n,t)和g(n,t)表示在当前结点未搜索过的子树的起始编号和终止编号
            for( int i = f(n,t); i <= g(n,t); ++i){
                x[t] = h(i);
                //constraint和bound分别是约束函数和界限函数
                if(constraint(t) && Bound(t)) 
                    Backtrack(t+1);
            }
        }
    }
    一边喊着救命,一边享受沉沦。
  • 相关阅读:
    Different AG groups have the exactly same group_id value if the group names are same and the ‘CLUSTER_TYPE = EXTERNAL/NONE’
    An example of polybase for Oracle
    use azure data studio to create external table for oracle
    Missing MSI and MSP files
    You may fail to backup log or restore log after TDE certification/key rotation.
    Password is required when adding a database to AG group if the database has a master key
    Use KTPASS instead of adden to configure mssql.keytab
    ardunio+舵机
    android webview 全屏100%显示图片
    glide 长方形图片显示圆角问题
  • 原文地址:https://www.cnblogs.com/fast-walking/p/8930343.html
Copyright © 2011-2022 走看看