代码改变世界

随笔分类 -  算法---回溯法

回溯之子集树和排列树(子集和问题)

2015-03-05 17:09 by youxin, 3662 阅读, 收藏, 编辑
摘要: 一、子集树 子集树:当所给的问题是从n个元素的集合S中找出满足某种性质的子集时,相应的解空间称为子集树。例如,那个物品的0-1背包问题所相应的解空间树就是一颗子集树。这类子集问题通常有2^n个叶节点,其节点总个数为2^(n+1)-1。遍历子集树的任何算法均需要O(2^n)的计算时间。\void ... 阅读全文

排列 或组合问题的解法(包含回溯法)

2013-08-31 20:15 by youxin, 2803 阅读, 收藏, 编辑
摘要: 排列:(A、B、C、D)的全排列为1、A后面跟(B、C、D)的全排列2、B后面跟(A、C、D)的全排列3、C后面跟(A、B、D)的全排列4、D后面跟(A、B、C)的全排列void permutation(int a[], int m, int k) { if (k>m) { ... 阅读全文

回溯法解0/1背包问题

2013-08-22 14:34 by youxin, 975 阅读, 收藏, 编辑
摘要: 我们前面说过,贪心算法用价值重量比对于可分割的背包问题是有效的,但对于0/1背包问题就无效的(0/1背包是不能分割,要就要,不要就不要)。本节用回溯法解0/1背包问题,求解过程如下:在搜索过程中,尽量沿着左儿子节点前进,当不能沿着左儿子节点继续前进时,就得到问题的一个部分解,并把搜索转移到右儿子子树。此时,估计由这个部分解所能得到的最大价值,把该值与当前的上界进行比较,如果高于当前的上界,就继续由右儿子子树向下搜索,扩大这个部分解,直到找到一个可行解,最后把可行解保存起来,用当前可行解的值刷新目标函数的上界,并向上回溯,寻找其他可能解;如果有部分所估计的最大值小于当前的上界,就丢弃正在搜索的部 阅读全文

回溯法求解哈密顿回路问题

2013-08-21 14:52 by youxin, 5835 阅读, 收藏, 编辑
摘要: 假设图中有n个顶点1,2,3,4,5,6,7用x[i] 存储问题的解。x[1]存储初始点,x[2]存储第二个点。以此类推。bool b[n+1][n+1] 存储图的邻接矩阵。约束条件:xi!=xj 0 #includeusing namespace std; bool b[100][100]; //图的邻接矩阵 bool check(int x[],int n, int k){ for(int i=1;i1) { x[k]+=1; while(x[k]>n; int *x=new int[n+1]; int edges;... 阅读全文

回溯法求幂集

2013-07-27 15:08 by youxin, 1794 阅读, 收藏, 编辑
摘要: 集合A的幂集是由集合A的所有子集所组成的的集合,如:A={1,2,3},则A的幂集P(A)={{1,2,3},{1,2},{1,3},{1},{2,3},{2},{3},{ }},求一个集合的幂集就是求一个集合的所有的子集,方法有穷举法,分治法,回溯等,这里主要介绍一下回溯法。 回溯法是设计递归过程的一种重要的方法,它的求解过实质上是一个先序遍历一棵“状态树”的过程,只是这棵树不是遍历前预先建立的,而是隐含在遍历过程中的。 幂集中的每个元素是一个集合,它或是空集,或含集合A中一个元素,或含集合A中两个元素…… 或等于集合A。反之,从集合A 的每个元素来看,它只有两种状态:它或属幂集的无素集,. 阅读全文

回溯法求排列问题

2012-07-15 20:09 by youxin, 956 阅读, 收藏, 编辑
摘要: 问题:输出n的全排列1. 问题描述: 输出自然数1到n的所有不重复的排列,即n的全排列。2. 问题分析:(1) 解空间: n的全排列是一组n元一维向量(x1, x2, x3, ... , xn),搜索空间是:1#includeusing namespace std;int count=0;//解个数int n;//输入数据int *a ;//解向量int *d ;//解状态void clear( ){ for(int i=1;i>n; a=new int[n+5];//解向量 d=new int[n+5];//解状态 clear( ); tryArran... 阅读全文

回溯法解哈密顿问题

2012-07-12 17:46 by youxin, 1888 阅读, 收藏, 编辑
摘要: 回溯法求解: 首先把回路中的所有顶点编号初始化为0,然后,把顶点0当做回路中的第0个顶点,即x0=0;搜索与0邻接的编号最小的顶点,作为它的后续顶点,判断是否满足约束条件,是则到达该顶点,x1取值为满足条件的顶点编号,然后再以同样的方式搜索。 假设在搜索过程中已经生成了通路L=x0x1....,xi-1,在继续搜索某个顶点作为通路的xi顶点时,根据约束条件,在V中选择与xi-1邻接的并且不属于L的编号最小的顶点。 如果搜索成功,则把该顶点作为xi,否则就把L中的xi-1删去(回溯),从xi-1顶点编号加1的位置开始,继续搜索与xi-2相邻接且不属于L的顶点。这个过程一直继续下去。 当搜... 阅读全文

回溯法解马的遍历问题

2012-06-08 15:36 by youxin, 3391 阅读, 收藏, 编辑
摘要: 马的遍历问题:在n*m的棋盘上,马只能走日字。马从位置(x,y)处出发,把棋盘的每一点都走一次,且只走一次,找出所有路径。问题分析:行n,列m,马在不出边界的情况下有8个方向可以行走(走日字),如当前坐标为(x,y),则行走后的坐标可以为:(x+1,y+2) (x+1,y-2), (x+2,y+1) (x+2,y-1)(x-1,y-2) (x-1,y+2) (x-2,y-1) (x-2,y+1)回溯法算法设计: 搜索空间是n*M个点,约束条件是不出边界且每个点只经过一次,节点的扩展规则如上所述。 搜索过程是从任一点(x,y)出发,按深度优先原则,从8个方向尝试一个可以走的点,直到走过n*m个. 阅读全文

回溯法解八后问题

2012-05-20 22:58 by youxin, 639 阅读, 收藏, 编辑
摘要: 在一个8×8国际象棋盘上,有8个皇后,每个皇后占一格;要求皇后间不会出现相互“攻击”的现象,即不能有两个皇后处在同一行、同一列或同一对角线上。问共有多少种不同的方法。 我们用回溯法,现在的目的不是找有多少种解法,而是只要找出一种合适的解法输出即可。先写一个place函数,判断当前位置是否合法:bool place(int x[],int k){ int i; for(i=1;i0) { x[k]=x[k]+1; //在当前列加1的位置开始搜索,这句很重要 while(x[k]0)假设有4个皇后。仔细想想,假设当k=1此时a[k]=4; a[k]还... 阅读全文

回溯法简介

2012-05-20 15:53 by youxin, 1692 阅读, 收藏, 编辑
摘要: 回溯法(探索与回溯法)是一种选优搜索法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。有许多问题,当需要找出它的解集或者要求回答什么解是满足某些约束条件的最佳解时,往往要使用回溯法。回溯法的基本做法是搜索,或是一种组织得井井有条的、能避免不必要搜索的穷举式搜索法。这种方法适用于解一些组合数相当大的问题。回溯法在问题的解空间树中,按深度优先策略,从根结点出发搜索解空间树。算法搜索至解空间树的任意一点时,先判断该结点是否包含问题的解:如果肯定不包含,则跳过对该. 阅读全文