`

回溯法之一---算法框架及基础

阅读更多

回溯法其实也是一种搜索算法,它可以方便的搜索解空间。
回溯法解题通常可以从以下三步入手:
1、针对问题,定义解空间
2、确定易于搜索的解空间结构
3、以深度优先的方式搜索解空间,并在搜索的过程中进行剪枝
回溯法通常在解空间树上进行搜索,而解空间树通常有子集树和排列树。
针对这两个问题,算法的框架基本如下:
用回溯法搜索子集合树的一般框架:

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);
     }
  }
}


用回溯法搜索排列树的算法框架:

void backtrack(int t){
  if(t > n) output(x);
  else{
    for(int i = f(n,t); i <= g(n,t);i++){
          swap(x[t],x[i]);
          if(constraint(t) && bound(t)) backtrack(t+1);
          swap(x[t],x[i]); 
    }
  }
}


其中f(n,t),g(n,t)表示当前扩展结点处未搜索过的子树的起始标号和终止标号,
h(i)表示当前扩展节点处,x[t]第i个可选值。constraint(t)和bound(t)是当前
扩展结点处的约束函数和限界函数。constraint(t)返回true时,在当前扩展结点
x[1:t]取值满足约束条件,否则不满足约束条件,可减去相应的子树。bound(t)返
回的值为true时,在当前扩展结点x[1:x]处取值未使目标函数越界,还需要由backtrack(t+1)
对其相应的子树进一步搜索。
用回溯法其实质上是提供了搜索解空间的方法,当我们能够搜遍解空间时,
显然我们就能够找到最优的或者满足条件的解。这便是可行性的问题, 而效率可以
通过剪枝函数来降低。但事实上一旦解空间的结构确定了,很大程度上时间复杂度
也就确定了,所以选择易于搜索的解空间很重要。
下面我们看看两个最简单的回溯问题,他们也代表了两种搜索类型的问题:子集合问题和
排列问题。
第一个问题:
求集合s的所有子集(不包括空集),我们可以按照第一个框架来写代码:

#include<iostream>
using namespace std;

int s[3] = {1,3,6};
int x[3];
int  N = 3;
void print(){
   for(int j = 0; j < N; j++)
	if(x[j] == 1)
	   cout << s[j] << " ";
   cout << endl;
}

void subset(int i){
 	if(i >= N){
        print();
	    return;
	}

	x[i] = 1;//搜索右子树
	subset(i+1);
	x[i] = 0;//搜索左子树
	subset(i+1);
}

int main(){
  subset(0);
  return 0;
}



下面我们看第二个问题:排列的问题,求一个集合元素的全排列。
我们可以按照第二个框架写出代码:

#include<iostream>
using namespace std;

int a[4] = {1,2,3,4};
const int N = 4;

void print(){
	for(int i = 0; i < N; i++)
		   cout << a[i] << " ";
    cout << endl;
}

void swap(int *a,int i,int j){
  int temp;
  temp = a[i];
  a[i] = a[j];
  a[j] = temp;
}

void backtrack(int i){
	if(i >= N){
		print();
	}
	for(int j = i; j < N; j++){
		swap(a,i,j);
		backtrack(i+1);
		swap(a,i,j);
	}
}

int main(){
  backtrack(0);
  return 0;
}


这两个问题很有代表性,事实上有许多问题都是从这两个问题演变而来的。第一个问题,它穷举了所有问题的子集,这是所有第一种类型的基础,第二个问题,它给出了穷举所有排列的方法,这是所有的第二种类型的问题的基础。理解这两个问题,是回溯算法的基础.
下面看看一个较简单的问题:
整数集合s和一个整数sum,求集合s的所有子集su,使得su的元素之和为sum。
这个问题很显然是个子集合问题,我们很容易就可以把第一段代码修改成这个问题的代码:

int sum = 10;
int r = 0;
int s[5] = {1,3,6,4,2};
int x[5];
int  N = 5;

void print(){
   for(int j = 0; j < N; j++)
	if(x[j] == 1)
	   cout << s[j] << " ";
   cout << endl;
}
void sumSet(int i){
	if(i >= N){
		if(sum == r) print();
	    return;
	}
	if(r < sum){//搜索右子树
	  r += s[i];
	  x[i] = 1;
	  sumSet(i+1);
	  r -= s[i]; 
	}
	x[i] = 0;//搜索左子树
	sumSet(i+1);
}

int main(){
  sumSet(0);
  return 0;
}

 

 permute

4
1
分享到:
评论
4 楼 fuliang 2008-04-18  
引用

写的不错,兄弟你是做搜索的吧

没错,做web挖掘,搜索引擎方面的
3 楼 zhouchun 2008-04-18  
写的不错,兄弟你是做搜索的吧
2 楼 david19842003 2008-03-06  
很好,很适合入门:)
1 楼 fuliang 2008-02-25  
其实搜索可以说是可以优化的穷举,我们可以通过剪枝函数提前剪掉不可行的解,从而提高效率。回溯提供了穷举的一种方法,并且这种方法适合于剪枝。

相关推荐

    利用回溯法解0-1背包问题讲解

    回溯算法框架: * 问题的解空间:应用回溯法解问题时,首先应明确定义问题的解空间。 * 回溯法的基本思想:确定了解空间的组织结构后,回溯法就从开始结点(根结点)出发,以深度优先的方式搜索整个解空间。 * 递归...

    回溯法实现0-1背包问题

    针对这一问题,C++语言提供了一种灵活且强大的编程框架,可以实现高效的回溯法算法。在编写程序时,首先需要设计背包结构体,这个结构体通常包含物品的重量、价值、序号等属性。定义好结构体后,便可以依据特定的...

    算法分析之回溯法算法框架课件

    "算法分析之回溯法算法框架课件" 该课件主要介绍了回溯法算法框架的基本概念、原理和应用。回溯法是一种搜索算法,用于解决组合优化问题。该算法框架的核心思想是通过深度优先搜索来探索解空间,找到问题的最优解。...

    回溯算法 0-1 背包算法

    在回溯法框架下,我们需要执行以下步骤: 1. **定义解空间**:解空间是由所有可能的物品选择集合构成的,每个节点代表一种可能的选择状态。在0-1背包问题中,解空间可以用一个二维数组表示,其中数组的每个元素表示...

    用c++实现的 0-1背包 回溯法

    算法框架: a.. 问题的解空间:应用回溯法解问题时,首先应明确定义问题的解空间。问题的解空间应到少包含问题的一个(最优)解。 b. 回溯法的基本思想:确定了解空间的组织结构后,回溯法就从开始结点(根结点...

    中科大 算法导论 课件(全套11)回溯法

    - **教学意义**: 在中国科学技术大学的算法导论课程中,回溯法作为计算机科学与技术专业学生必须掌握的重要内容之一,有助于培养学生的算法设计与分析能力。 **2. 搜索算法简介** - **穷举搜索**: 对所有可能的...

    算法分析与设计PPT 回溯法

    回溯法是一种在解决问题时采用的算法策略,尤其适用于解决组合优化问题。它的核心思想是通过深度优先搜索来...在设计回溯法算法时,我们需要明确问题的解空间,选择合适的搜索策略,并引入适当的剪枝函数来提高效率。

    C++类库与算法 STL 算法与分析 皇后问题回溯法实现程序源代码 回溯法示例代码

    本主题聚焦于C++类库与算法的应用,特别是标准模板库(STL)中的算法,并通过一个具体的实例——皇后问题的回溯法实现来深入探讨。 皇后问题是一个经典的计算机科学问题,它要求在棋盘上放置N个皇后,使得任意两个...

    五大常用算法之回溯法,算法数据结构

    回溯法是一种重要的算法策略,尤其适用于解决复杂的问题,如组合优化问题和约束满足问题。它基于深度优先搜索,通过尝试不同的解决方案并适时回溯来找到有效解或所有解。以下将详细介绍回溯法的基本概念、思想以及...

    算法设计与分析 回溯法

    回溯法是一种重要的算法设计策略,常用于解决复杂的问题,如搜索、组合优化和逻辑推理等。它通过尝试所有可能的解空间分支来寻找问题的解,当发现某一分支无法得到有效解时,会“回溯”到上一步,尝试其他分支。这种...

    c++之回溯法(通用算法)

    回溯法是一种强大的算法,常用于解决组合优化问题和搜索问题,如迷宫求解、八皇后问题等。它的核心思想是通过试探性地构造可能的解决方案,并在构造过程中逐步检查每个步骤,如果发现当前路径无法导出有效解,则撤销...

    第5章 回溯法.pdf

    在理解回溯法之前,需要掌握其算法框架,其中包含四个主要方面:递归回溯、迭代回溯、子集树算法框架以及排列树算法框架。递归回溯是一种通过递归调用函数本身来实现的回溯,而迭代回溯则是在循环结构中实现的。子集...

    回溯法处理骑士游历问题

    dfs中的回溯法,poj2488骑士游历,主要是回溯要将所有的点都遍历到。

    回溯法 0-1背包源代码

    #### 3.1 算法框架 在本程序中,主要通过一个名为`Knap`的类实现了0-1背包问题的回溯法求解。该类包含两个私有成员函数:`Bound`和`Backtrack`。 - **Bound** 函数计算当前状态下的上界。上界是指从当前状态出发所...

    回溯法讲义 ppt版

    回溯法是一种强大的算法,常用于解决复杂的问题,如组合优化和约束满足问题。它采用深度优先搜索策略,尤其适用于解空间较大的问题。在回溯法中,问题的解通常被表示为一个向量,每个元素代表解的一部分,且可能受到...

    计算机软件及应用算法分析回溯法PPT课件.pptx

    在学习回溯法时,学生需要掌握的关键点包括回溯法的算法框架、基本思想以及应用实例。只有深入理解回溯法的原理,才能在遇到复杂的组合优化问题时,灵活运用回溯法,找到高效的解决方案。为了达到这一目的,PPT课件...

    算法8_回溯法n1

    3. 回溯法的算法框架:回溯法有两种主要的实现方式,递归回溯和迭代回溯。递归回溯通过函数调用实现深度优先搜索,当达到问题状态的边界时,如果发现当前分支无法产生解,就回溯到上一层继续尝试。迭代回溯则使用栈...

    算法设计 回溯法

    经典算法 回溯法。学习算法,必定知道。5.1 回溯法算法框架 5.2 装载问题 5.3 批处理作业调度 5.4 符号三角形问题 5.5 n后问题 5.6 0-1背包问题 5.8 图的m着色问题 5.9 旅行售货员问题

    算法与数据结构之回溯法

    回溯法是一种基于试探性的解决问题的方法,常用于解决组合优化问题。它通过深度优先搜索解空间树,尝试构造潜在的解决方案。当发现当前路径无法导出有效解时,回溯法会撤销最近的选择,尝试其他可能的分支,直到找到...

Global site tag (gtag.js) - Google Analytics