回溯法

子集和数问题——回溯法

点点圈 提交于 2019-11-30 16:37:35
子集和数问题——回溯法 回溯算法可以用来求最优解,也可以用来搜索某些问题的答案。回溯法又叫做试探法,它是以深度优先遍历的方式找各种符合要求的答案,在查找过程中伴随着一些减枝函数来提高效率。这种算法比较简单,比较出名的问题有8皇后问题。这个子集和数问题也可以用回溯法搞定。。。 所谓子集和数问题,就是给定你一个数的集合M,再给你一个数num,找出所有属于M且和为num的数的集合。比如M={1,2,3} num=3,则N为{1,2}和{3}。这些都比较简单,还是直接上代码吧。。。 public class SubNum { // 初始化化一个数组 int M[] = {1,2,3,4,5,6,7,8,9}; int N[] = new int[9]; //用来标识在某种组合中某个数字是否出现 boolean [] judge =new boolean [9]; int num;//给定的num int temp;//保存和 // 初始化化num public SubNum(int num) { this.num = num; } // 采用回溯法解决。。 public void findSub() { for (int a = 0; a < M.length; a++) { for (int b = a + 1; b < M.length; b++) { for(int i=0;i<M

剑指offer(27)字符串的排列

只谈情不闲聊 提交于 2019-11-30 07:59:53
题目描述 输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。 输入描述:输入一个字符串,长度不超过9(可能有字符重复),字符只包括大小写字母。 题目分析 这题还算可以,关于全排列,有两种解法,第一种就是递归全排列法,第二种就是回溯法。 递归全排列法: 就是剑指offer上的做法,也比较容易理解,不过挺少人答的也就是 把字符串分为两部分:第一部分为第一个字符,第二部分为第一个字符以后的字符串。 然后接下来求后面那部分的全排列。 再将第一个字符与后面的那部分字符逐个交换 回溯法 也就是利用树去尝试不同的可能性,不断地去字符串数组里面拿一个字符出来拼接字符串,当字符串数组被拿空时,就把结果添加进结果数组里,然后回溯上一层。(通过往数组加回去字符以及拼接的字符串减少一个来回溯。) 代码 回溯法: // 回溯法 function Permutation(str) { let res = []; const pStr = '' ; if (str.length <= 0) return res; arr = str.split(''); // 将字符串转化为字符数组 res = permutate(arr, pStr, res); return res; }

回溯法典型题目总结

三世轮回 提交于 2019-11-30 06:10:47
1. 求一个集合的全部子集。 思路:原集合中的每个元素有两种选择,要么加入要么不加入,所有元素的选择放在一起可构成了一系列等长向量,所有可能的等长向量构成了解空间。 import java.util.ArrayList; import java.util.List; public class Main{ public static void main(String[] args){ int[] nums = {1,2,3}; Backtrace A = new Backtrace(); List<List<Integer>> res = A.findAllSubSet(nums); System.out.println(res); } } class Backtrace{ boolean[] isExist; List<List<Integer>> res = new ArrayList<>(); public List<List<Integer>> findAllSubSet(int[] nums){ isExist = new boolean[nums.length]; backtrace(0, nums); return res; } public void backtrace(int index, int[] nums){ if(index == nums.length){

回溯法求迷宫问题

試著忘記壹切 提交于 2019-11-28 18:18:56
回溯法(探索与回溯法)是一种选优搜索法,又称为试探法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。 本文使用回溯法求解迷宫问题 迷宫问题,有一个m行n列的矩阵代表迷宫,1代表此路不通,0代表此路通。指定入口和出口,判断是否能从入口进,从出口走出。此程序只判断从路口到出口是否能走通,找到的路不一定是最短路(最短路的程序在下一篇中使用BFS算法给出),注意:从入口到出口可能没有路径或者不止一条路径。此处迷宫走法是8个方向,分别是左上,上,右上,右,右下,下,左下,左。程序中使用offsets myMove给出八个方向的表示。 include <iostream> #include <stack> using namespace std; struct offsets { int a,b;//a,b是x,y方向的偏移 char* dir;//dir方向 }; offsets myMove[8] = {//各个方向的偏移表 {-1,0,"N"}, {-1,1,"NE"}, {0,1,"E"}, {1,1,"SE"}, {1,0,"S"}, {1,-1,"SW"}, {0,-1,"W"}, {-1,0-1,"NW"} }; struct items {

回溯法求解迷宫问题

倾然丶 夕夏残阳落幕 提交于 2019-11-28 18:18:36
引言 最近在leetcode上看了些算法题,有些看着很简单的很常用的东西,竟然一下子想不出来怎么求解,比如说: 实现sqrt函数 , 求数组的排列 。如果高数学的不好,这些看似简单的问题,第一次碰到也会感觉很难求解,当然了,今天要说的是这样一个问题,求解迷宫的所有解,这个问题的求解用到了回溯法的思想,不了解这个思想的话,很多稍微复杂点的问题都很难解了。 问题描述 这个问题是在实在瞎逛的时候碰到的,具体哪里记不太清了。 1 1 1 1 0 1 0 1 0 1 0 1 0 1 1 1 上面是一个迷宫,左上角是入口,右下角是出口,小萌(对,你没看错,是长了草的小明)从入口进入,从出口逃出(1个小时逃不出会被X怪物吃掉),其中1表示可以通行,0表示不能通行,只能向右和向下两个方向走,求出所有的小萌可能逃生的路线。 这个问题看似挺简单,一下就可以看到答案,但是将思想翻译为代码却不知道从何入手了。 如何解决 解决这个问题的一种方案就是回溯法,先一起看看回溯法(百度百科)的定义: 回溯法(探索与回溯法)是一种选优搜索法,又称为试探法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。 我的思路: 对上面的迷宫进行坐标化,左上角是(0,0),右下角是(3,3)

回溯法-------迷宫问题

别说谁变了你拦得住时间么 提交于 2019-11-28 18:18:20
迷宫问题 1 #include <iostream> 2 using namespace std; 3 4 int flag = 0; 5 const int m = 5; 6 const int n = 5; 7 int a[m][n] = { 8 {0,0,0,1,1}, 9 {1,0,0,0,0},10 {0,1,1,0,1},11 {1,0,0,0,0},12 {0,1,0,1,0}13 };14 void search(int x,int y)15 {16 if((x==m-1)&&(y==n-1)) //当到达出口时,设置标志为117 flag = 1;18 else 19 {20 a[x][y] = 1;21 if( (!flag) && (y!=n-1) && (a[x][y+1]==0) ) search(x,y+1); //向右走22 if( (!flag) && (x!=m-1) && (a[x+1][y]==0) ) search(x+1,y); //向下走23 if( (!flag) && (y!=0) && (a[x][y-1]==0) ) search(x,y-1); //向左走24 if( (!flag) && (x!=0) && (a[x-1][y]==0) ) search(x-1,y); //向上走25 }26 a[x][y] = 0;27

回溯法-迷宫问题

自作多情 提交于 2019-11-28 18:18:08
回溯法(探索与回溯法)是一种选优搜索法,又称为试探法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯 条件 的某个 状态 的点称为“回溯点”。 我们用回溯法来写迷宫问题,如下: maze = [[0, 0, 1, 1, 1, 1, 1, 1], [1, 0, 1, 0, 1, 1, 0, 1], [1, 0, 0, 1, 1, 1, 0, 1], [1, 0, 1, 0, 0, 0, 0, 1], [1, 0, 0, 0, 1, 0, 1, 1], [1, 1, 1, 0, 1, 0, 1, 1], [1, 0, 0, 0, 1, 0, 0, 1], [1, 1, 1, 1, 1, 1, 0, 1]]stack = []dirs = [(0, 1), (1, 0), (0, -1), (-1, 0)]def mark(m, p): m[p[0]][p[1]] = 2def judge(m, p): return m[p[0]][p[1]] == 0def maze_solver(m, s, e): if s == e: print(s) return mark(m, s) stack.append(s) while len(stack): pos = stack[-1]

noj算法 迷宫问题 回溯法

梦想的初衷 提交于 2019-11-28 18:17:56
描述: 给一个20×20的迷宫、起点坐标和终点坐标,问从起点是否能到达终点。 输入: 多个测例。输入的第一行是一个整数n,表示测例的个数。接下来是n个测例,每个测例占21行,第一行四个整数x1,y1,x2,y2是起止点的位置(坐标从零开始),(x1,y1)是起点,(x2,y2)是终点。下面20行每行20个字符,’.’表示空格;’X’表示墙。 输出: 每个测例的输出占一行,输出Yes或No。 输入样例: 2 0 0 19 19 .................... XXXXXXXXXXXXXXXXXXXX .................... .................... .................... .................... .................... .................... .................... .................... .................... .................... .................... .................... .................... .................... .................... .................... .......

Rat in a Maze 回溯法解迷宫

眉间皱痕 提交于 2019-11-28 09:50:49
一个迷宫被给出为n*n二进制矩阵的块,其中源块是最左上方的块,即Maze[0][0],目标块是最右下方的块,即Maze[n-1][n-1]。老鼠从源头出发,必须到达目的地。老鼠只能朝两个方向移动:向前和向下。 在迷宫矩阵中,0表示块是死端,1表示块可以用于从源到目标的路径。请注意,这是典型迷宫问题的简单版本。例如,更复杂的版本可能是老鼠可以向四个方向移动,而更复杂的版本可能移动的次数有限。 下面是一个迷宫的例子。 Backtracking 回溯法的三部曲: 1 初始化原始数据,开始点 2 判断下一步是否合法,如果合法就继续递归搜索答案,如果不合法就返回 3 递归直到找到答案,返回真值 这里只需要找到一个解就可以,所以只要找到一个解就可以马上返回。 /* A Maze is given as N*N binary matrix of blocks where source block is the upper left most block i.e., maze[0][0] and destination block is lower rightmost block i.e., maze[N-1][N-1]. A rat starts from source and has to reach destination. The rat can move only in two

机器人运动范围——回溯法应用

核能气质少年 提交于 2019-11-27 20:49:36
1. 和前面矩阵路径一样,即是使用递归,探索性前进,遍历各种情况 前面那个主函数里有循环是因为它可以从一个矩阵中的任意位置进入!! 我们这个题是只能从起始点(0,0)进入,用不到循环,但是访问过的节点也不能继续访问了!!(0,0)也满足要求,所以最差也是count=1; 注意:这个是行和列坐标不大于K(阈值),不是等于阈值!注意读题! 地上有一个m行和n列的方格。一个机器人从坐标0,0的格子开始移动,每一次只能向左,右,上,下四个方向移动一格, 但是不能进入行坐标和列坐标的数位之和大于k的格子。 例如,当k为18时,机器人能够进入方格(35,37),因为3+5+3+7 = 18。 但是,它不能进入方格(35,38),因为3+5+3+8 = 19。请问该机器人能够达到多少个格子? class Solution { public: int movingCount(int threshold, int rows, int cols) //阈值 { if(rows<1||cols<1||threshold<1) return 0; bool * visited=new bool[rows*cols]; memset(visited,0,rows*cols);//全都进行置位操作 int count= movingCountCore(threshold,rows,cols,0,0