当前位置:首页 > 经验 >

回溯是什么含义(历史回溯是什么意思)

来源:原点资讯(www.yd166.com)时间:2022-10-30 22:43:24作者:YD166手机阅读>>

回溯法

对于回溯法,网上有很多种解释,这里我依照自己的(死宅)观点做了以下三种通俗易懂的解释:

  • 正经版解释:其实人生就像一颗充满了分支的n叉树,你的每一个选择都会使你走向不同的路线,获得不同的结局。如果能重来,我要选李白~呸!说错了,如果能重来,我们就能回溯到以前,选择到最美好的结局。
  • 游戏版解释:玩过互动电影游戏(如 行尸走肉)的都知道,你的每个选择都会影响游戏的结局,掌控他人的生死。每次选择错误导致主角或配角死亡,我们是不是回溯读档,希望得到一个更好的结局。PS:克莱曼婷天下无敌!
  • 动漫版解释:看过主角拥有死亡回归(疯狂暗示486)的都知道,主角的每个选择都能影响大局,可是486直接能回溯重选,这与我们今天要讲的回溯法极其相似。PS:爱蜜莉雅、雷姆我都要!

专业名词

  • 解空间: 即 所有的可能情况

概念

回溯算法:是类似于枚举的搜索尝试过程,主要是在搜索尝试过程中寻找问题的解,当发现已不满足求解条件时,就“回溯”返回,尝试别的路径。

它是一种选优搜索法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术称为 回溯法 ,而满足回溯条件的某个状态的点称为 “回溯点” (你也可以理解为 存档点 )。

回溯是什么含义,历史回溯是什么意思(1)

上图为八皇后的解空间树, 如果当前点不符合要求就退回再走

许多复杂的,规模较大的问题都可以使用回溯法,有“通用解题方法”的美称。

基本思想

在包含问题的所有解的解空间树中,按照 深度优先搜索 的策略,从根结点出发深度探索解空间树。

当探索到某一结点时,要先判断该结点是否包含问题的解:

  • 如果 包含 ,就从该结点出发继续探索下去;
  • 如果该结点 不包含 问题的解,则逐层向其祖先结点回溯。(其实回溯法就是对隐式图的深度优先搜索算法)

结束条件:

  • 若用回溯法求问题的 所有解 时,要回溯到根,且根结点的所有可行的子树都要已被搜索遍才结束。
  • 若使用回溯法求 任一个解 时,只要搜索到问题的一个解就可以结束。

网上的一般步骤

虽然我觉得网上的一般步骤太抽象了,但是还是摆在这里供大家参考吧。。

  1. 针对所给问题,确定问题的解空间:首先应明确定义问题的解空间,问题的解空间应至少包含问题的一个(最优)解。
  2. 确定结点的扩展搜索规则:及时确定规则,并不是每个解空间都要走完才能发现是死路的,有时候走到一半就发现不满足条件了。
  3. 以深度优先方式搜索解空间,并在搜索过程中 用剪枝函数避免无效搜索:不满足条件的路径及时剪掉(即 剪枝),避免继续走下去浪费时间。类比:比如说 削苹果 ,我们规定:苹果皮必须不断,要完整地削完整个苹果。那么,如果我们削到一半苹果皮断掉了,我们就可以直接退回去(即 回溯)换个苹果削了,如果继续削下去,只会浪费时间。

算法框架

问题框架:

设问题的 是一个 n维向量(a1,a2,………,an)约束条件ai(i=1,2,3,…..,n)之间 满足某种条件,记为 f(ai)

非递归回溯框架

其中, a[n] 为解空间, i 为搜索的深度,框架如下:

int a[n],i; //a[n]为解空间,i为深度 初始化数组 a[]; i = 1; while (i>0(有路可走) and (未达到目标)) { //还未回溯到头 if(i > n) { //搜索到叶结点 搜索到一个解,输出; } else { //处理第 i 个元素 a[i]第一个可能的值; while(a[i]在不满足约束条件且在搜索空间内) { a[i]下一个可能的值; }//while if(a[i]在搜索空间内) { 标识占用的资源; i = i 1; //扩展下一个结点 } else { 清理所占的状态空间; //回溯 i = i – 1; }//else }//else }//while

递归回溯框架

回溯法是对解空间的 深度优先搜索 ,在一般情况下使用 递归函数 来实现回溯法比较简单。

其中, a[n] 为解空间, i 为搜索的深度,框架如下:

int a[n]; //a[n]为解空间 BackTrace(int i) { //尝试函数,i为深度 if(i>n) { 输出结果; } else { for(j = 下界; j <= 上界; j=j 1) { //枚举 i 所有可能的路径 if(check(j)) { //检查满足限界函数和约束条件 a[i] = j; ... //其他操作 BackTrace(i 1); 回溯前的清理工作(如 a[i]置空值等); }//if }//for }//else }//BackTrace

回溯四步走

由于上述网上的步骤太抽象了,所以在这里我自己总结了回溯四步走:

  • 编写检测函数:检测函数用来检测此路径是否满足题目条件,是否能通过。这步不做硬性要求。。不一定需要
  1. 明确函数功能:要清楚你写这个函数是想要做什么;
  2. 寻找递归出口:一般为某深度,或叶子节点。
  3. 明确所有路径(选择) 这个构思路径最好用 树形图 表示。例如:走迷宫有上下左右四个方向,也就是说我们站在一个点处有四种选择,我们可以画成无限向下延伸的四叉树。直到向下延伸到叶子节点,那里便是出口;从根节点到叶子节点沿途所经过的节点就是我们满足题目条件的选择。
  4. 回溯还原现场:若 该节点所有选择已做完却仍然没有找到出口 ,那么我们需要 回溯还原现场 ,将该节点重置为初始状态,回溯到一切都没有发生的时候,再退回去。注意:回溯还原现场是必要的,如果不还原现场,那你的回溯有什么意义呢。。类比:大雄出意外了,哆啦A梦坐时空机回到过去想要改变这一切,结果过去的一切都没有被重置到初始状态,回到过去大雄还是现在这种受伤的样子没有改变,那么回到过去有什么意义呢。

编写检测函数(非必须)

第一步,写出检测函数,来检测这个路径是否满足条件,是否能通过。

这个函数依据题目要求来编写,当然,如果要求不止一个,可能需要编写多个检测函数。

例如:凑算式

回溯是什么含义,历史回溯是什么意思(2)

这个算式中A~I代表1~9的数字,不同的字母代表不同的数字。

比如:

6 8/3 952/714 就是一种解法,

5 3/1 972/486 是另一种解法。

这个算式一共有多少种解法?

要做出这个题,

第一步,要写出检测函数

public static int sum = 0; // 用来存放总共的解法数 public static double[] a = new double[10]; // 判断数组里前j个元素是否与t相同 /** * @param a 传入一个数组a * @param j 判断前j个元素 * @param t 是否与t相同 * @return */ public static boolean same(double[] a, int j, int t) { for (int i = 1; i < j; i ) { if (a[i] == t) { return true; } } return false; } /** * @param a 判断a数组是否满足表达式 * @return 如果满足就true,不满足就false */ public static boolean expression(double[] a) { if ((a[1] a[2] / a[3] (a[4] * 100 a[5] * 10 a[6]) / (a[7] * 100 a[8] * 10 a[9]) == 10)) return true; else return false; }

明确函数功能

由于此题要填数字,所以我们定义choose(i)的含义为:在算式中自动填入数字 i 。

寻找递归出口

第二步,要寻找递归出口,当1~9均已填入后,判断表达式是否成立,若成立,则输出。

// 如果选择的数字大于9,则代表1~9均已选完,判断是否满足表达式,输出选择的表达式 if (i > 9) { if (expression(a)) { for (int x = 1; x < 10; x ) { System.out.print(a[x] " "); } System.out.println(); sum ; } return; }

明确所有路径

第三步,要知道这个递归是几个选择,即 几叉树。

此题为1~9九个选择,九条路,九叉树。

for (int j = 1; j <= 9; j ) { // 如果将要填入的数与前面不冲突,则填入 if (!same(a, i, j)) { a[i] = j; choose(i 1); } }

回溯还原现场

第四步,若该节点没有找到出口,则将当前位置回溯,还原现场,重新选择

在本题中, 还原现场 即 重置为0(表示还未填入1~9的数字)

for (int j = 1; j <= 9; j ) { // 如果将要填入的数与前面不冲突,则填入 if (!same(a, i, j)) { a[i] = j; choose(i 1); //若没有找到出口,则将当前位置重置为0,回溯,还原现场 a[i] = 0; } }

实例

凑算式

回溯是什么含义,历史回溯是什么意思(3)

这个算式中A~I代表1~9的数字,不同的字母代表不同的数字。

比如:

6 8/3 952/714 就是一种解法,

5 3/1 972/486 是另一种解法。

这个算式一共有多少种解法?

答案:

// 凑算式 public class Sy1 { public static void main(String[] args) { // TODO Auto-generated method stub choose(1); System.out.println("一共" sum "种解法"); } public static int sum = 0; // 用来存放总共的解法数 public static double[] a = new double[10]; // 判断数组里前j个元素是否与t相同 /** * @param a 传入一个数组a * @param j 判断前j个元素 * @param t 是否与t相同 * @return */ public static boolean same(double[] a, int j, int t) { for (int i = 1; i < j; i ) { if (a[i] == t) { return true; } } return false; } /** * @param a 判断a数组是否满足表达式 * @return 如果满足就true,不满足就false */ public static boolean expression(double[] a) { if ((a[1] a[2] / a[3] (a[4] * 100 a[5] * 10 a[6]) / (a[7] * 100 a[8] * 10 a[9]) == 10)) return true; else return false; } /** * @param i 选择第i个数字 递归 */ public static void choose(int i) { // 如果选择的数字大于9,则代表1~9均已选完,输出选择的表达式 if (i > 9) { if (expression(a)) { for (int x = 1; x < 10; x ) { System.out.print(a[x] " "); } System.out.println(); sum ; } return; } for (int j = 1; j <= 9; j ) { // 如果将要填入的数与前面不冲突,则填入 if (!same(a, i, j)) { a[i] = j; choose(i 1); //若没有找到出口,则将当前位置重置为0,回溯,还原现场 a[i] = 0; } } } }

程序运行结果:

3.0 5.0 1.0 9.0 7.0 2.0 4.0 8.0 6.0 4.0 9.0 3.0 5.0 2.0 8.0 1.0 7.0 6.0 5.0 3.0 1.0 9.0 7.0 2.0 4.0 8.0 6.0 5.0 4.0 3.0 7.0 2.0 6.0 1.0 9.0 8.0 5.0 4.0 9.0 7.0 3.0 8.0 1.0 6.0 2.0 5.0 8.0 6.0 4.0 7.0 3.0 1.0 2.0 9.0 6.0 4.0 2.0 3.0 5.0 8.0 1.0 7.0 9.0 6.0 4.0 2.0 7.0 1.0 8.0 3.0 5.0 9.0 6.0 7.0 3.0 4.0 8.0 5.0 2.0 9.0 1.0 6.0 8.0 3.0 9.0 5.0 2.0 7.0 1.0 4.0 6.0 9.0 8.0 4.0 3.0 7.0 1.0 5.0 2.0 7.0 1.0 4.0 9.0 6.0 8.0 3.0 5.0 2.0 7.0 3.0 2.0 8.0 1.0 9.0 5.0 4.0 6.0 7.0 3.0 2.0 9.0 8.0 1.0 6.0 5.0 4.0 7.0 5.0 3.0 2.0 6.0 4.0 1.0 9.0 8.0 7.0 5.0 3.0 9.0 1.0 2.0 6.0 8.0 4.0 7.0 9.0 6.0 3.0 8.0 1.0 2.0 5.0 4.0 7.0 9.0 6.0 8.0 1.0 3.0 5.0 4.0 2.0 8.0 1.0 3.0 4.0 6.0 5.0 2.0 7.0 9.0 8.0 6.0 9.0 7.0 1.0 2.0 5.0 3.0 4.0 8.0 7.0 6.0 1.0 9.0 5.0 2.0 3.0 4.0 9.0 1.0 3.0 4.0 5.0 2.0 6.0 7.0 8.0 9.0 1.0 3.0 5.0 2.0 4.0 7.0 8.0 6.0 9.0 2.0 4.0 1.0 7.0 8.0 3.0 5.0 6.0 9.0 2.0 4.0 3.0 5.0 8.0 7.0 1.0 6.0 9.0 3.0 4.0 1.0 5.0 7.0 6.0 2.0 8.0 9.0 4.0 8.0 1.0 7.0 6.0 3.0 5.0 2.0 9.0 4.0 8.0 3.0 5.0 6.0 7.0 1.0 2.0 9.0 6.0 8.0 1.0 4.0 3.0 5.0 7.0 2.0 一共29种解法

方格填数

如下的10个格子填入0~9的数字。

回溯是什么含义,历史回溯是什么意思(4)

首页 1234下一页

栏目热文

回溯时间(前世回溯催眠引导音频)

回溯时间(前世回溯催眠引导音频)

《回溯咖啡馆》是由三昧漫画出品的原创漫画作品,由你猜我叫啥主笔,小扣童稚编剧以及洋葱小猪、吕太浪等辅助制作的悬疑剧情向漫...

2022-10-30 22:33:36查看全文 >>

时间维度是什么意思(时间维度)

时间维度是什么意思(时间维度)

如果世界是虚拟的,那人类怎么办?其实最早提出这个设想的并不是世界首富埃隆马斯克,而是科幻电影《骇客帝国》,那时,好莱坞世...

2022-10-30 23:02:51查看全文 >>

时间的回溯是什么意思(回溯7天什么意思)

时间的回溯是什么意思(回溯7天什么意思)

我是枚说游戏,一个励志做精品游戏知识分享的游戏人,关注点赞收看更多更好玩的内容!红警三部曲都是因为时间机器导致的一代的开...

2022-10-30 22:43:26查看全文 >>

回溯是什么意思啊(回溯的意思和含义)

回溯是什么意思啊(回溯的意思和含义)

回溯法就是一种有组织的系统化搜索技术,可以看作是蛮力法穷举搜索的改进。回溯法每次只构造可能解的一部分,然后评估这个部分解...

2022-10-30 22:55:54查看全文 >>

剩余时间是指什么意思(空闲时间是指什么)

剩余时间是指什么意思(空闲时间是指什么)

来源:环球时报 【环球时报综合报道】“美国人下个月将前往投票站,参与自国会山骚乱以来的首次重大政治测验。”《纽约时报》这...

2022-10-30 23:08:35查看全文 >>

保险可回溯是什么意思(保险回溯环节)

保险可回溯是什么意思(保险回溯环节)

消费者在选购一些保险产品时,有时候会遇到“可回溯”环节,但是,在保险实务中,却有不少消费者因为各种原因对这一环节不是很重...

2022-10-30 23:00:27查看全文 >>

回溯是什么意思呢(回溯怎么解释)

回溯是什么意思呢(回溯怎么解释)

质量回溯=根本原因分析与解决&持续改进。 由质量控制和质量回溯两者构成闭环。质量控制目的是质量水平的保持,质量回...

2022-10-30 22:31:54查看全文 >>

时间轨迹是什么意思(时间思维是什么意思)

时间轨迹是什么意思(时间思维是什么意思)

2022年10月10日10时55分,黑龙江齐齐哈尔市收到外省发来的协查信息:10月9日外省某市发现一名核酸检测阳性人员,...

2022-10-30 23:10:58查看全文 >>

追溯历史还是回溯历史(目前中国可追溯到的最早历史)

追溯历史还是回溯历史(目前中国可追溯到的最早历史)

随着我国医院信息化管理建设的发展和深入,采用信息化技术实现CSSD管理,将成为医院CSSD发展的必然趋势。那么究竟一个好...

2022-10-30 22:42:26查看全文 >>

有效时间是指什么意思(尿液不能超过几小时化验)

有效时间是指什么意思(尿液不能超过几小时化验)

行政处罚的追诉时效,又称追责时效或者追究时效,是指行政机关对当事人违反行政管理秩序的行为,依法给予行政处罚的有效期限。若...

2022-10-30 22:36:18查看全文 >>

文档排行