回溯法

递归回溯

 由于回溯法是对解空间的深度优先搜索,因此在一般情况下可用递归函数来实现回溯法如下:

t表示递归深度,即当前扩展节点在解空间树的深度。

n用来控制递归深度。当t>n时表示算法搜索到叶节点。

void backtrack( int t )

{

if ( t>n )

output(x);

else

for( int i=f(n,t); i<=g(n,t); i++ ) {

x[t]=h(i);

if ( constraint(t)&&bound(t) )

backtrack(t+1);

}

}

迭代回溯

 采用树的非递归深度优先遍列算法,可将回溯法表示为一个非递归迭代过程。

solution(t)判断当前扩展节点是否得到问题的可行解。

void iterativeBacktrack( )

{ int t=1;

while ( t>0 ) {

if ( f(n,t)<=g(n,t) )

for( int i=f(n,t); i<=g(n,t); i++ ) {

x[t]=h(i);

if ( constraint(t)&&bound(t) ) {

if ( solution(t) )  output(x);

else t++;  }

}

else t--;

}

}

用回溯法搜索子集树的一般算法描述为:

void backtrack( int t )

{

if ( t>n )

output(x);

else

for( int i=0; i<=1; i++ ) {

x[t]=i;

if ( constraint(t)&&bound(t) )

backtrack(t+1);

}

}

用回溯法搜索排列树的一般算法描述为:

void backtrack( int t )

{

if ( t>n )

output(x);

else

for( int i=t; i<=n; i++ ) {

swap(x[t], x[i] );

if ( constraint(t)&&bound(t) )

backtrack(t+1);

swap(x[t], x[i] );

}

}

public  class  Loading
{
   //类的数据成员
 static  int  n;          //集装箱数
 static  int[]  w;      //集装箱重量数组
 static  int  c;          //第一艘轮船的载重量
    static  int  cw;      //当前载重量
    static  int  bestw;   //当前最优载重量

   public  static  int  maxLoading ( int [] ww, int cc )
   {  //初始化类数据成员
       n=ww.length – 1;   w=ww;
       c=cc;  cw=0;  bestw=0;
       //计算最优载重量
  backtrack(1);
       return  bestw;
   }
   //回溯算法
   private  static  void  backtrack( int t )
   { //搜索第i层节点
    if ( i>n ) {  //到达叶节点
       if (cw>bestw)  bestw=cw;
          return;   }
      //搜索子树
      if  (cw+w[I]<=c)  {  //搜索左子树,即x[i]=1
           cw+=w[i];
           backtrack(i+1);
           cw-=w[i];
       }
      backtrack(t+1);        //搜索右子树
  }
}
public  class  Loading
{
   //类的数据成员
 static  int  n;          //集装箱数
 static  int[]  w;      //集装箱重量数组
 static  int  c;          //第一艘轮船的载重量
    static  int  cw;      //当前载重量
    static  int  bestw;   //当前最优载重量
    static  int  r;         //剩余集装箱的重量

   public  static  int  maxLoading ( int [] ww, int cc )
   {  //初始化类数据成员
       n=ww.length – 1;   w=ww;  c=cc;  cw=0;  bestw=0;
        //初始化
        for(int i=1; i<=n; i++)  r+=w[i];
       //计算最优载重量
  backtrack(1);   return  bestw;
   }
   //回溯算法
   private  static  void  backtrack( int t )
   { //搜索第i层节点
    if ( i>n ) {  //到达叶节点
       if (cw>bestw)  bestw=cw;
          return;   }
      //搜索子树
      r - = w[i];
      if  (cw+w[i]<=c)  {  //搜索左子树
           cw+=w[i];   backtrack(i+1);   cw -=w[i];
       }
      if  (cw+w[i]>bestw)      //搜索右子树
          backtrack(t+1);
      r + = w[i];
  }
}
构造最优解
public  class  Loading
{    //类的数据成员
 static  int  n;          //集装箱数
 static  int[]  w;      //集装箱重量数组
 static  int  c;          //第一艘轮船的载重量
    static  int  cw;      //当前载重量
    static  int  bestw;   //当前最优载重量
 static  int  r;         //剩余集装箱的重量
 static  int[]  x;         //当前解
 static  int[]  bestx;      //当前最优解

   public  static  int  maxLoading ( int [] ww, int cc )
   {  //初始化类数据成员
       n=ww.length – 1; w=ww; c=cc; cw=0; bestw=0; x=new int[n+1];  bestx=xx;
        //初始化
        for(int i=1; i<=n; i++)  r+=w[i];
       //计算最优载重量
  backtrack(1);   return  bestw;
   }
   //回溯算法
   private  static  void  backtrack( int t )
   { //搜索第i层节点
     if ( i>n ) {  //到达叶节点
         for( int j=1; j<=n; j++ )  bestx[j]=x[j];
         bestw=cw;
         return;   }
      //搜索子树
      r - = w[i];
      if  (cw+w[i]<=c)  {  //搜索左子树
           x[i]=1;  cw+=w[i];   backtrack(i+1);   cw -=w[i];
       }
      if  (cw+w[i]>bestw)   {   //搜索右子树
          x[i]=0; backtrack(t+1);    }
      r + = w[i];
}

迭代回溯

 由于数组x记录了解空间从根节点至当前扩展节点的路径,这些信息已包含了回溯法所需的信息。利用数组x的信息可以改为非递归的形式。

回溯法,布布扣,bubuko.com

时间: 2024-08-24 16:23:43

回溯法的相关文章

五大常用算法之四:回溯法

(转自:http://www.cnblogs.com/steven_oyj/archive/2010/05/22/1741376.html) 1.概念 回溯算法实际上一个类似枚举的搜索尝试过程,主要是在搜索尝试过程中寻找问题的解,当发现已不满足求解条件时,就“回溯”返回,尝试别的路径. 回溯法是一种选优搜索法,按选优条件向前搜索,以达到目标.但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”. 许

回溯法 -数据结构与算法

1.回溯法算法思想: 定义: 回溯法(探索与回溯法)是一种选优搜索法,按选优条件向前搜索,以达到目标.但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”. 1.回溯法适用:有许多问题,当需要找出它的解集(全部解)或者要求回答什么解是满足某些约束条件的最优解时,往往要使用回溯法. 2.有组织的穷举式搜索:回溯法的基本做法是搜索或者有的组织穷尽搜索.它能避免搜索所有的可能性.即避免不必要的搜索.这种方

0-1背包-回溯法

算法描述: 0-1背包的回溯法,与装载问题的回溯法十分相似.在搜索解空间树时,只要其左儿子结点是一个可行结点,搜索就进入其左子树.当右子树中有可能包含最优解时才进入右子树进行搜索.否则将右子树剪去. 计算右子树上界的更好算法是: 将剩余物品依其单位重量价值排序,然后依次装入物品,直至装不下时,再装入该物品的一部分而装满背包. 算法实现: 由Bound函数计算当前节点处的上界. 类Knap的数据成员记录解空间树的节点信息,以减少参数传递及递归调用所需的栈空间. 在解空间树的当前扩展结点处,仅当要进

回溯法浅谈

回溯法是初学者学习暴力法的第一个障碍,所谓回溯就是指当把问题分成若干步骤并递归求解时,如果当前步骤没有合法选择,则函数将返回上一级递归调用,这种现象称为回溯.正是因为这个原因,递归枚举算法常被称为回溯法,应用十分普遍. 八皇后问题 1 int tot=0; 2 int c[maxn]; //c[x]表示x行所在的列数 3 void dfs(int n,int cur){ 4 if(cur==n) ++tot; 5 for(int i=0;i<n;i++){ 6 int flag=0; 7 c[c

回溯法求迷宫问题

回溯法(探索与回溯法)是一种选优搜索法,又称为试探法,按选优条件向前搜索,以达到目标.但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”.本文使用回溯法求解迷宫问题迷宫问题,有一个m行n列的矩阵代表迷宫,1代表此路不通,0代表此路通.指定入口和出口,判断是否能从入口进,从出口走出.此程序只判断从路口到出口是否能走通,找到的路不一定是最短路(最短路的程序在下一篇中使用BFS算法给出),注意:从入口到

经典算法学习之回溯法

回溯法的应用范围:只要能把待求解的问题分成不太多的步骤,每个步骤又只有不太多的选择就可以考虑使用回溯法. 若用回溯法求问题的所有解时,要回溯到根,且根结点的所有可行的子树都要已被搜索遍才结束. 而若使用回溯法求任一个解时,只要搜索到问题的一个解就可以结束. 回溯法将问题的候选解按照某一顺序逐一枚举和检验.当发现当前候选解不可能是解时,就选择下一个候选解,若当前候选解符合要求,且还未达到求解的规模,则继续扩展当前候 选解的规模,如果候选解已经满足了所有要求,并且也达到了问题的规模,那么该候选解就是

回溯法-01背包问题之一:递归模式

一.回溯法 回溯法是一个既带有系统性又带有跳跃性的搜索算法.它在包含问题的所有解的解空间树中按照深度优先的策略,从根节点出发搜索解空间树.算法搜索至解空间树的任一节点时,总是先判断该节点是否肯定不包含问题的解.如果肯定不包含,则跳过对以该节点为根的子树的系统搜索,逐层向其原先节点回溯.否则,进入该子树,继续按深度优先的策略进行搜索. 运用回溯法解题通常包含以下三个步骤: · 针对所给问题,定义问题的解空间: · 确定易于搜索的解空间结构: · 以深度优先的方式搜索解空间,并且在搜索过程中用剪枝函

算法入门经典-第七章 例题7-4-1 拓展 n皇后问题 回溯法

实际上回溯法有暴力破解的意思在里面,解决一个问题,一路走到底,路无法通,返回寻找另   一条路. 回溯法可以解决很多的问题,如:N皇后问题和迷宫问题. 一.概念 回溯算法实际类似枚举的搜索尝试过程,主要是在搜索尝试过程中寻找问题的解,当发现不满足条件的时候,就回溯返回,尝试别的路径. 百度解释:回溯法(探索与回溯法)是一种选优搜索法,又称为试探法,按选优条件向前搜索,以达到目标.但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯

回溯法之八皇后问题简单理解

回溯法,简单理解就是有源可溯.基本思想要借鉴穷举法,但是它不是一味地穷举,当发现某一步不符合条件时,这一步后面的穷举操作就不进行了(俗称“剪枝”),我自己把它叫做动态穷举法.假设第一个步骤可行,那么执行第二个步骤,第三个......如果其中第三个步骤不行,那么我们再回过来(回溯),第二个步骤换一种方法尝试,然后再重新第三个步骤,第四个......直到完成任务要求为止. 这里,以八皇后问题为例.试图把回溯法讲清楚. 注意:递归应该是一种算法结构,回溯法是一种算法思想. 何为八皇后问题? (百度百科