回溯法

回溯算法

亡梦爱人 提交于 2020-03-24 08:40:16
   回溯法(探索与回溯法)是一种选优搜索法,又称为试探法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯 条件 的某个 状态 的点称为“回溯点”。 皇后问题:   八皇后问题:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。 class NQueensII { public: int* x;//当前解 int N;//皇后个数 int sum = 0;//当前已找到的可行方案数 int totalNQueens(int n) { N = n; x = new int[N + 1]; backTrace(1); return sum; } /** * col行这个点,x[col]列这个点,与已经存在的几个皇后,是否符合要求,放到这个位置上, * @param col * @return */ bool place(int col) { for (int i = 1; i < col; i++) { if (abs(col - i) == abs(x[col] - x[i]) || x[col] == x[i]) { return false; } } return true; } void

利用回溯法解决八皇后问题(循环)

独自空忆成欢 提交于 2020-03-17 08:02:45
利用回溯法解决八皇后问题(循环) 2.用循环解决 # include <stdio.h> # include <stdlib.h> int a [ 20 ] , n , sum ; void output ( ) //输出 { int i , j ; for ( i = 1 ; i <= n ; i ++ ) { for ( j = 1 ; j <= n ; j ++ ) { if ( a [ i ] == j ) printf ( " Q" ) ; else printf ( " *" ) ; } printf ( "\n" ) ; } printf ( "\n" ) ; } int check ( int k ) //检查当前位置是否可放 { int i ; for ( i = 1 ; i <= k - 1 ; i ++ ) //abs(a[i] - a[k])==abs(i - k))用于判断当前位置是否在前面任一皇后的左下斜线或右下斜线方向 //(a[i]==a[k])用于判断当前位置是否在前面任一皇后的正下方 if ( ( abs ( a [ i ] - a [ k ] ) == abs ( i - k ) ) || ( a [ i ] == a [ k ] ) ) return 0 ; //不可以放 return 1 ; //可以放 } void backdate (

1、算法初识

痴心易碎 提交于 2020-03-05 12:42:10
1.什么是 算法 ? 算法(Algorithm)是指解题方案的准确而完整的描述,是一系列解决问题的清晰指令,算法代表着用系统的方法描述解决问题的策略机制。 也就是说,能够对一定规范的输入,在有限时间内获得所要求的输出。 如果一个算法有缺陷,或不适合于某个问题,执行这个算法将不会解决这个问题。 不同的算法可能用不同的时间、空间或效率来完成同样的任务。 一个算法的优劣可以用空间复杂度与时间复杂度来衡量。 算法中的指令描述的是一个计算,当其运行时能从一个初始状态和(可能为空的)初始输入开始,经过一系列有限而清晰定义的状态,最终产生输出并停止于一个终态。 一个状态到另一个状态的转移不一定是确定的。随机化算法在内的一些算法,包含了一些随机输入。 1.1特征 一个算法应该具有以下五个重要的特征: 有穷性 (Finiteness) 算法的有穷性是指算法必须能在执行有限个步骤之后终止; 确切性 (Definiteness) 算法的每一步骤必须有确切的定义; 输入项 (Input) 一个算法有0个或多个输入,以刻画运算对象的初始情况,所谓0个输入是指算法本身定出了初始条件; 输出项 (Output) 一个算法有一个或多个输出,以反映对输入数据加工后的结果。没有输出的算法是毫无意义的; 可行性 (Effectiveness) 算法中执行的任何计算步骤都是可以被分解为基本的可执行的操作步

n后问题-回溯法

我们两清 提交于 2020-02-22 07:27:03
问题描述:   在n*n的棋盘上放置彼此不受攻击的n个皇后。按国际象棋的规则,皇后可以与之处在同一行或者同一列或同一斜线上的棋子。   n后问题等价于在n*n格的棋盘上放置n皇后,任何2个皇后不放在同一行或同一列的斜线上。 算法设计:   |i-k|=|j-l|成立,就说明2个皇后在同一条斜线上。可以设计一个place函数,测试是否满足这个条件。   1 当i>n时,算法搜索至叶节点,得到一个新的n皇后互不攻击放置方案,当前已找到的可行方案sum加1.   2 当i<=n时,当前扩展结点Z是解空间中的内部结点。该结点有x[i]=1,2,3....n共n个儿子节点。     对当前扩展结点Z的每个儿子节点,由place检察其可行性。并以深度优先的方式递归地对可行子树,或剪去不可行子树。 算法描述:  #include <iostream> #include <cstdlib> using namespace std; class Queen{ friend int nQueen(int); private: bool Place(int k); void Backtrack(int t); int n, * x; long sum; }; bool Queen::Place(int k) { for(int j=1;j<k;j++) if((abs(k-j)==abs(x[j]-x

回溯法

那年仲夏 提交于 2020-02-18 03:48:36
回溯法 的主要思想就是每次只构造解的一个分量,然后按照一定的方法评估这个部分构造解。如果一个部分构造解可以进一步构造而不会违反问题的约束,我们就接受对解的下一个分量所做的第一个合法的选择。如果无法对下一个分量进行合法的选择,就不必对剩下的任何分量再做任何选择。在这种情况下,算法进行 回溯 ,把部分构造解的最后一个分量替换为合法的另一个选择。 来源: CSDN 作者: 日光浴_05 链接: https://blog.csdn.net/futurech/article/details/104358859

利用回溯法解排列组合问题

☆樱花仙子☆ 提交于 2020-02-17 06:36:59
回溯法简述 回溯法是一种优选的搜索法,又称试探法。按选优条件向前搜索,已达到目标。但当搜索到某一步时,发现原选择并不优或者达不到目标,就退一步重新选择。这种走不通就退回再走的技术称为回溯法。详见之前的文章 回溯法总结 。 排列组合例题 以下三道为leetcode上有关排列组合的问题,分别是46、47和48题。 第一题:46. Permutations Given a collection of distinct integers, return all possible permutations. Example: Input: [1,2,3] Output: [ [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1] ] class Solution { public List<List<Integer>> permute(int[] nums) { List<List<Integer>> list = new ArrayList<>(); backtrack(list, new ArrayList<>(), nums); return list; } private void backtrack(List<List<Integer>> list, List<Integer> tempList, int [] nums){ if

K-N皇后问题,回溯法、BFS、DFS,任意数量种类的皇后在棋盘上的摆放方案

两盒软妹~` 提交于 2020-02-15 00:59:12
对最大为MAX*MAX的棋盘,任意数量种的皇后,种类数量以queen记录,每种皇后的同一行,同一列,以及对角线上不能有其他同种类的皇后,一个格子只能放一个皇后棋子,计算最多摆放方案的数量,并记录在ans[][]内,输出方案数量。 判断对角线用 abs(行-行) == abs(列-列) 后续再更新优化,用二进制保存数据判断运算。 # include <iostream> # include <cmath> # include <cstring> # define MAX 13 //棋盘最大范围 # define queen 2 //两种棋 using namespace std ; int N ; int rst = 0 ; bool map [ MAX ] [ MAX ] ; int ans [ queen ] [ MAX ] ; void test ( ) { //测试数据 N = 13 ; for ( int i = 0 ; i < N ; ++ i ) { for ( int j = 0 ; j < N ; ++ j ) { map [ i ] [ j ] = 1 ; } } } void inputData ( ) { cin >> N ; for ( int i = 0 ; i < N ; ++ i ) { for ( int j = 0 ; j < N ; ++ j )

回溯算法思想

杀马特。学长 韩版系。学妹 提交于 2020-02-11 17:05:01
一、回溯算法主要思想   回溯法有“通用的解题法”之称。用它可以系统地搜索一个问题的所有解或任一解。回溯法是一个既带有系统性又带有跳跃性的搜索算法,它在问题的解空间树中,按深度优先策略,从根节点出发搜索解空间树。算法搜索至解空间树的任一结点时,先判断该结点是否包含问题的解。如果不包含,则跳过对以该结点为根的子树的搜索,逐层向其祖先结点回溯。否则进入该子树,继续按深度优先策略搜索。回溯算法求问题的所有解时,要回溯到根,且根结点的所有子树都已被搜索遍才结束。回溯法求问题的一个解时,只要搜索到问题的一个解就可结束。这种以深度优先方式系统搜索问题解的算法称为回溯算法,它适用于解组合较大的问题。   确定了解空间的组织结构后,回溯法从开始结点(根结点)出发,以深度优先方式搜索整个解空间。这个开始结点成为活结点,同时也成为当前的扩展结点。在当前的扩展结点处,搜索向纵深方向移至一个新结点。这个新结点就成为新的活结点,并成为当前扩展结点。如果在当前的扩展结点处不能再向纵深方向移动,则当前扩展结点就成为死结点。此时,应往回移动(回溯)至最近的一个活结点处,并使这个活结点成为当前的扩展结点。回溯法以这种工作方式递归地在解空间中搜索,直至找到所要求的解或解空间中已无活结点时为止。 二、用回溯法解题通常包括以下 3 个步骤 (1)针对所给问题,定义问题的解空间; (2)确定易于搜索的解空间结构; (3

leetcode 46 全排列(初识回溯)

杀马特。学长 韩版系。学妹 提交于 2020-02-08 02:07:13
回溯法的理解: 先从选择列表中进行选择,然后进行回溯(递归),之后撤销当前的选择。 回溯法主要包括以下两个变量: 选择列表 决策路径 回溯法的框架: result = [ ] def backtrack ( 路径 , 选择列表 ) : if 满足结束条件 : result . add ( 路径 ) return for 选择 in 选择列表 : 做选择 backtrack ( 路径 , 选择列表 ) 撤销选择 对于本题,除了应用回溯法进行查找,还要对选择过的元素进行标记,不再进行选择,避免重复。 其中,nums[:i] + nums[i+1:]就实现了从nums中删除已经选择的元素。 本题的代码: class Solution : def permute ( self , nums ) : result = [ ] nums_length = len ( nums ) def backtrack ( nums , answer = [ ] ) : if len ( answer ) == nums_length : result . append ( answer ) for i in range ( len ( nums ) ) : backtrack ( nums [ : i ] + nums [ i + 1 : ] , answer + [ nums [ i ] ] )

八皇后问题递归回溯法

穿精又带淫゛_ 提交于 2020-02-06 02:53:03
写在前面:最开始接触是数据结构老师在提到过,后来在学python时老师也有提到过,出于好奇就去思考了这个问题,当然,小白的我还是在B站懒猫老师的帮助下学会啦,真棒哈哈哈哈哈哈 这里主要问题是在于判断对角线上是否能放,表示上对角线d1[],表示下对角线d2[],根据老师所说加上自己的理解,同一个下对角线上 n-col+7相同(n表示行,col表示列) 同理,上对角线上n+col 相同 由以上可得判断的标准为(flag[col]&&d1[n-col+7]&&d2[n+col]==ture),只要符合这个就能判断是否能放入棋子 place[n]=col;//摆放皇后 flag[col]=false;//宣布占领第col列 d1[n-col+7]=false;//占领上对角线 d2[n+col]=false;//占领下对角线 #include<stdio.h> #include <stdbool.h> int place[8]={0}; //第n个皇后所占位置的列号 bool flag[8]={1,1,1,1,1,1,1,1}; //标志数组,表示第col列是否可占,1表示不冲突 bool d1[15]={1,1,1,1.1,1.1,1,1,1,1,1,1,1,1}; bool d2[15]={1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}; //表示下对角线是否可占 int