回溯法

每日刷题191203 --回溯算法

99封情书 提交于 2019-12-06 10:28:32
  虽然不是每天都刷,但还是不想改标题,(手动狗头   题目及解法来自于力扣(LeetCode), 传送门 。 算法(78) : 给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。 说明:解集不能包含重复的子集。 示例: 输入: nums = [1,2,3] 输出: [ [3], [1], [2], [1,2,3], [1,3], [2,3], [1,2], [] ]   这道题我自己其实一开始没有什么比较好的想法,希望能用循环来解决,但写着写着发现处理情况有些多/循环嵌套次数过多。来一起看看网友给的解法吧,回溯法: 1 public class Solution { 2 //回溯法 3 private IList<IList<int>> res; 4 private void find(int[] nums, int begin, IList<int> pre) 5 { 6 // 没有显式的递归终止 7 res.Add(new List<int>(pre));// 注意:这里要 new 一下 8 for (int i = begin; i < nums.Length; i++) 9 { 10 pre.Add(nums[i]); 11 find(nums, i + 1, pre); 12 pre.RemoveAt(pre.Count - 1);//

算法笔记05 --- 回溯法

末鹿安然 提交于 2019-12-06 06:13:39
概述   在搜索尝试过程中寻找问题的解,当发现已不满足求解条件时,就“回溯”返回,尝试别的路径。   回溯法是一种选优搜索法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。 在包含问题的所有解的解空间树中,按照深度优先搜索的策略,从根结点出发深度探索解空间树。当探索到某一结点时,要先判断该结点是否包含问题的解,如果包含,就从该结点出发继续探索下去,如果该结点不包含问题的解,则逐层向其祖先结点回溯。(其实回溯法就是对隐式图的深度优先搜索算法)。   若用回溯法求问题的所有解时,要回溯到根,且根结点的所有可行的子树都要已被搜索遍才结束。   而若使用回溯法求任一个解时,只要搜索到问题的一个解就可以结束。 解题思路 针对所给问题,确定问题的解空间:首先应明确定义问题的解空间,问题的解空间应至少包含问题的一个(最优)解;   确定结点的扩展搜索规则;   以 深度优先 方式搜索解空间,并在搜索过程中用剪枝函数避免无效搜索 应用场景 来源: https://www.cnblogs.com/clarino/p/11965094.html

八皇后问题—经典回溯算法

余生颓废 提交于 2019-12-05 21:52:28
八皇后问题 八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。 高斯认为有76种方案。1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果。 回溯算法思想 回溯算法的基本思想是:从一条路往前走,能进则进,不能进则退回来,换一条路再试。八皇后问题就是回溯算法的典型,第一步按照顺序放一个皇后,然后第二步符合要求放第2个皇后,如果没有位置符合要求,那么就要改变第一个皇后的位置,重新放第2个皇后的位置,直到找到符合条件的位置就可以了。回溯在迷宫搜索中使用很常见,就是这条路走不通,然后返回前一个路口,继续下一条路。回溯算法说白了就是穷举法。不过回溯算法使用剪枝函数,剪去一些不可能到达最终状态(即答案状态)的节点,从而减少状态空间树节点的生成。回溯法是一个既带有系统性又带有跳跃性的的搜索算法。它在包含问题的所有解的解空间树中,按照深度优先的策略,从根结点出发搜索解空间树。算法搜索至解空间树的任一结点时,总是先判断该结点是否肯定不包含问题的解。如果肯定不包含,则跳过对以该结点为根的子树的系统搜索,逐层向其祖先结点回溯。否则,进入该子树,继续按深度优先的策略进行搜索

回溯法--八皇后问题

这一生的挚爱 提交于 2019-12-05 10:01:26
def queene(n): helpQueene([-1]*n,0,n) def helpQueene(columnPositions,rowIndex,n): global count if rowIndex == n: count+=1 printSolution(columnPositions,n) return for column in range(n): columnPositions[rowIndex]=column if isValid(columnPositions,rowIndex): helpQueene(columnPositions,rowIndex+1,n) def isValid(columnPositions,rowIndex): for i in range(rowIndex): if columnPositions[i] == columnPositions[rowIndex]: return False elif abs(columnPositions[i]-columnPositions[rowIndex])==(rowIndex-i): return False return True def printSolution(columnPositions,n): for row in range(n): line="" for column

五大算法-1.回溯法

风流意气都作罢 提交于 2019-12-05 03:12:46
什么是回溯法? S: 回溯法官网概念是一个类似枚举搜素尝试的过程,是一种选优搜索树,按照某个条件来向前搜索,如果满足条件的时候,就“回溯”,返回到树的上一层,重新试探其他的结果,直到遍历完所有的解空间。个人理解就是该问题的解可以构建一棵解空间树,该题就可以使用回溯法来解决,下面我们使用了N皇后这个经典的问题来解释解空间树和回溯法。 问题实例:N皇后问题 在n×n格的棋盘上放置彼此不受攻击的n个皇后。按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。n后问题等价于再n×n的棋盘上放置n个皇后,任何2个皇后不妨在同一行或同一列或同一斜线上。 一下是3皇后问题中的解空间树 从上面的图示可以看出,3皇后问题的所有的解可以看成上述的一个n叉树问题,因为第一行的棋子有n中可能,对应第一行棋子的一种可能,第二种也有n种可能,如果使用回溯的方法的话,我们需要先将题目的所有解情况先存储起来,然后再对其中的每种情况进行判断是否符合条件,这做需要消耗大量的内存空间;同时在构建的这个解空间的树上,可能还没有走到叶子节点就会发现该情况不行,这样使用回溯法的时候我们就可以直接在该点回溯,也就是向树的上一父节点走,然后遍历父节点的其他情况,这样可以减少空间复杂的同时也减少了时间复杂度。 N皇后问题java代码实现: package com.leetcode; import java

算法笔记-回溯法

China☆狼群 提交于 2019-12-04 12:16:30
  (1)0-1背包问题    思路:构造一个二叉树,每个商品都有两种状态,要或者不要。如果要就在这个节点的左枝挂子节点,如果不要就在右节点挂子节点。如果全部商品都分配完状态之后就回溯,回溯到一个还有其他选择的节点,接着往这个选择发展节点,然后再回溯,然后再往下。。。。 直到无路可走,就结束了。       假如限制重量是10,总共有四个商品,重量分别是2, 5, 4, 2 价格分别是6, 3, 5, 4。第一轮的路程如5-11图,第1个商品要,第2个商品要,第3个商品发现装不下了,所以到第3个节点只能走右节点,并且第3个节点的左节点成为死节点,没有发展下去的可能了。第4个商品要,此时已经给所有的商品赋予状态了(要或者不要),记录下此时所有商品的价值和,记为最优价格。接着就开始回溯,如5-13,从节点5先是回溯到节点4(此时购物车有1,2,3选择不要,4肯定是要的,所以没必要再发展4节点的右节点),再到节点3(节点三的左节点是死节点),再到节点2,节点2的右节点是可选的,然后接着按照刚开始的逻辑接着往下走就可以了,等继续走完这一轮,计算最优值,更新下最优值,然后再回溯。。。       剪枝:如果按照上面的逻辑,其实几乎相当于遍历了所有的可能性。如果有4个商品,就会有2的4次方种可能,有些不可能是最优结果的分支直接就剪掉就可以了,比如,如果按照上面的逻辑是会有

回溯法解数独

巧了我就是萌 提交于 2019-12-03 16:36:44
数独 ,是源自18世纪瑞士的一种数学游戏。是一种运用纸、笔进行演算的逻辑游戏。玩家需要根据9×9盘面上的已知数字,推理出所有剩余空格的数字,并满足每一行、每一列、每一个粗线宫内的数字均含1-9,不重复。 数独盘面是个九宫,每一宫又分为九个小格。在这八十一格中给出一定的已知数字和解题条件,利用逻辑和推理,在其他的空格上填入1-9的数字。 使1-9每个数字在每一行、每一列和每一宫中都只出现一次 ,所以又称“ 九宫格 ”。 目标 对于一个给定的“残缺”的9 X 9棋盘,使用 回溯法 去给出一个解, 如有解则打印出一个解 ; 如果没有解,则输出没有找到相应的解法 。 如: 给定一个“残缺”的棋盘, ----------------------- | 3 | 1 7 | 2 8 | | 5 | 2 | 9 4 | | 6 2 | 9 | 1 7 | ----------------------- | 3 | 4 1 | 6 | | 4 7 | | 3 5 | | 2 | 3 | 1 | ----------------------- | 1 | 7 9 | 2 | | 9 | 8 2 | 4 | | 8 | 3 | 7 | ----------------------- 得到如下的一个结果。 ----------------------- | 3 9 4 | 5 1 7 | 6 2 8 |

装载问题(回溯法)

匿名 (未验证) 提交于 2019-12-03 00:18:01
1.具体问题 : 一批集装箱共n个要装上2艘载重量分别为c1和c2的轮船,其中集装箱i的重量为Wi且W1+W2+……+Wn<=c1+c2;试确定一个合理的装载方案使这n个集装箱装上这两艘轮船。 2.问题分析: 容易去证明:如果一个装载问题有解,则采用下面的策略可以得到最优装载方案: (1)首先将第一艘轮船尽可能装满; (2)然后将剩余的集装箱装在第二艘轮船上。 那么在这个过程中,我们需要找到尽可能把第一个轮船装满的解。如果用回溯法解决问题,我们可以首先分析问题得解空间结构,应该是一个子集树。然后我们可以把问题套入相应的模版进行解决。下面是代码示例: 3.代码示例 #include<stdio.h> #define M 100 int n=3;//装载问题的深度 int x[]={0,0,0};//用来标记是否放入第一艘轮船 int c1=50;//第一艘轮船剩余容量 int w[]={10,40,40};//货物重量 int x1[]={0,0,0};//标记最优解 int Constrain(int t){ int i; int sum=0; static int sum1=0; //最优解 for(i=0;i<=t;i++){ if(x[i]==1) sum+=w[i]; } printf("--------------->%d\n",sum); for(i=0;i<n;i++

回溯法

匿名 (未验证) 提交于 2019-12-02 23:43:01
1.回溯法编程求解0-1背包问题 #include<stdio.h> #include<iostream> using namespace std; int c,n; int cv=0,cw=0,mv=0,mw=0; int weight[20],value[20]; int x[20],bestv[20]; int backtrack(int t) { } int main() { } 2.利用回溯法编程求解TSP问题 #include<iostream> #include<algorithm> //记录当前正在计算路径的费用 void TSP(int t){ } int main(){ cout<<best [1]<<endl; system("pause"); }

圆排列问题-回溯法

匿名 (未验证) 提交于 2019-12-02 23:43:01
2019独角兽企业重金招聘Python工程师标准>>> 问题描述: 算法设计: 算法描述: #include <iostream> #include <math.h> #include <stdlib.h> #include < string .h> using namespace std; class Circle{ friend float CirclePerm( int , float * ); private : float Center( int t); void Compute( void ); void Backtrack( int t); float min,*x,* r; int n; }; float Circle::Center( int t) { float temp = 0 ; for ( int j= 1 ;j<t;j++ ) { float valuex=x[j]+ 2.0 *sqrt(r[t]* r[j]); if (valuex > temp) temp = valuex; } return temp; } void Circle::Compute( void ) { float low = 0 , high = 0 ; for ( int i= 1 ;i<=n;i++ ) { if (x[i]-r[i] < low) low = x[i]- r