递归回溯
测验
相关......
- 计算机科学>
回溯可以被认为是一种选择性的方法
假设你到了一片坏叶子。您可以通过撤销您最近的选择来继续搜索良好的叶子,并尝试在该组选项中的下一个选项。如果您的选项耗尽,请撤销此处的选择,并在该节点上尝试其他选择。如果您最终以剩余选项的obot,则没有良好的叶子。
回溯对于解决约束满足问题至关重要,例如纵横字谜、口头算术、数独和许多其他难题。它还用于解决背包问题、文本解析和其他组合优化问题。
关于回溯的有趣是我们只需要备份,以达到以前未开发的替代方案的先前决策点。一般来说,这将是最近的决定点。最终,越来越多的这些决策点将得到充分探索,我们将不得不进一步回顾。如果我们一直返回我们的初始状态并从那里探索了所有替代方案,我们可以得出结论是无法解决的特定问题。在这种情况下,我们将完成详尽递归的所有工作,并已知没有可行的解决方案。
置换
给定的一组项目的置换是元件的一定重新排列。可以显示一个数组 A.长度 N有 N!排列。例如,阵列['j','o','n']具有以下筛选:
1 2 3 4 5 6 |
|
这里应用的回溯算法相当直接,因为调用不受任何约束。我们不是从一个不需要的结果中回溯,我们只是回溯到一个以前的状态,而不过滤掉不需要的输出。下面的图片和代码对此进行了详细阐述:
如图所示,算法基于交换。实施后,在打印置换之后,回溯部分将物品交换给上一个位置。
以下python代码显示了如何完成此操作:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
它输出
1 2 3 4 5 6 7 |
|
迷你数独
Sudoku是一个逻辑拼图,其中目标是用数字填充网格,以便每个列,每行和构成网格的子网格中的每个子网格都包含来自的所有数字 1.到 N。相同的单个整数可能在同一行,列或子网格中出现两次。
让我们看看简化 3.×3.迷你版原始数独拼图。在这里,每个单元是一个含有的子级 1.元素,并且是平凡的不同元素。这意味着我们只需要检查行和列是否包含整数 1., 2.和 3.没有重复。
下面是一个迷你数独游戏(左)及其解决方案(右)的示例
现在应该是显而易见的,这种拼图是递归逆发的成熟。让我们现在铺设伪电讯,这将有助于我们解决它。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
上面的代码是回溯的经典示例。如果给定的电路板木板
应该在功能之外。
实现一个实际的mini 3.×3.解算器并使用它将解决方案打印到下面的拼图中
python中的示例解决方案
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64从itertools.进口*从复制进口复制def你与众不同吗(列表):'''辅助函数为is_solved检查列表中的所有元素是否不同(虽然忽略0s)'''用过的=[]对于我在列表:如果我==.0:持续如果我在用过的:返回假的用过的.追加(我)返回真的def已验证(brd):“检查3x3迷你数独游戏是否有效。”对于我在范围(3.):排=[brd[我] [0],brd[我] [1.],brd[我] [2.]如果不你与众不同吗(排):返回假的col=[brd[0] [我],brd[1.] [我],brd[2.] [我]如果不你与众不同吗(col):返回假的返回真的def解决(brd,空虚=9):'''解决一个迷你数独游戏brd是董事会成员empty是空单元格的数量'''如果空虚==.0:#基本情况返回已验证(brd)对于排,col在产品(范围(3.),重复=2.):#穿过每个细胞细胞=brd[排] [col]如果细胞!=0:#如果不是空跳跃持续brd2=复制(brd)对于测试在[1.,2.,3.]:brd2[排] [col]=测试如果已验证(brd2)和解决(brd2,空虚-1.):返回真的#backtrack.brd2[排] [col]=0返回假的董事会=[[0,0,0],[1.,0,0],[0,3.,1.]]解决(董事会,9-3.)对于排在董事会:#prints一个解决方案打印排
它输出
1 2 3 4>>> [3,1,2] [1,2,3] [2,3,1]
寻找路径
回溯的更实用和众所周知的例子是路径查找。机器人可以例如通过重复在路径上进行迷宫并从导致的位置返回到迷宫中的路径。这当然要求我们以算法与之兼容的方式来代表迷宫。常用方法是使用a 2.−D矩阵和其中的值表示障碍物或路径。以下是迷宫解决问题的简化版本,应该有助于澄清回溯算法。
简化路径发现问题
给予A. N×N带有源左上块的块矩阵,我们要找到从源到目标(右下块)的路径。我们只能向下和向左移动。另外,路径由 1.一堵墙是由 0.
以下是迷宫的示例(黑色细胞无法访问)
1 2 3 4 |
|
解决方案是如下:
我们现在可以概述一个回溯算法,返回包含坐标形式的路径的数组。例如,对于上面的图片,解决方案是 (0,0)→(1.,0)→(1.,1.)→(2.,1.)→(3.,1.)→(3.,2.)→(3.,3.)
1 2 3 4 5 6 |
|
Python的实现看起来像以下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 18 19 20 21 22 23 23 24 |
|
8 - 皇后书
与排列问题相反,这里我们将看到一个回溯的示例,它涉及检查许多约束。这听起来不太好,但有大量的约束实际上允许我们在回溯时显著减少搜索空间。这也意味着运行时间和性能有了实质性的改进。
解决方案的示例
图片来源:[维基百科]
计算机科学中回溯的一个非常常见的例子是放置问题 N跳棋棋盘上的皇后,没有两个皇后互相攻击。棋盘由以下部分组成: 8.×8.细胞。皇后队可以垂直,水平和对角线移动。问题在计算解决方案的数量,而不是枚举每个单独的解决方案。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
由于国际象棋的性质,在覆盖国际象棋板时,我们会在我们找到一个广场时削减搜索空间,我们不能给出我们的配置。回溯搜索在这里最有效,因为它消除了周围 95.%搜索空间的一部分。上面的伪代码详细说明了如何实现这一点。
在实际编写实现时,我们担心实际代表问题的数据结构和有效手段。下面的Python代码显示了如何解决回溯搜索的实现的示例。
8个女王的问题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 646.5.从itertools.进口*进口复制班董事会:''表示棋盘的类''def__在里面__(自己,N):#初始化类自己.木板=[[没有任何对于我在范围(8.)]对于我在范围(8.)]自己.件=设置()def__str__(自己):“允许我们打印电路板”s=''对于我在自己.木板:s+ =str(我)+'\ n'返回sdefPlaceQueen(自己,排,柱):''在第行第列放置皇后''自己.件.添加((排,柱))自己.木板[排] [柱]=“Q”def清除(自己,排,柱):''从给定的“行”和“列”中删除皇后''自己.木板[排] [柱]=没有任何自己.件.去除((排,柱))defisattaching.(自己,第一件,第二件):''检查piece1是否攻击piece2''如果第一件[0]==.第二件[0]或者第一件[1.]==.第二件[1.]:#检查它们是否在同一行或列中返回真的''检查它们是否正在攻击攻击这可以通过简单的代数有效地完成如果这两张图片在同一条对角线上满足包含两点'''的线的等式x1,y1,x2,y2=第一件[1.],第一件[0],第二件[1.],第二件[0]M=漂浮(y2-y1)/(x2-x1)如果防抱死制动系统(M)!=1.0:返回假的其他的:B=y2-M*x2返回y1==.M*x1+Bdef伊萨塔尼(自己,块):''检查一块是否atacked板“”中的任何其他块对于第一件在自己.件:如果自己.isattaching.(块,第一件):返回真的返回假的def恩奎恩斯(木板,N):如果N==.0:返回[木板]解决=[]我=0对于第一件在产品(范围(8.),重复=2.):如果第一件在木板.件:持续如果不木板.伊萨塔尼(第一件):我+ =1.新鲜的=复制.深透视(木板)新鲜的.PlaceQueen(第一件[0],第一件[1.])解决+ =恩奎恩斯(新鲜的,N-1.)返回解决
8个女王的问题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30'''投稿人:Bipin Oli'''def已验证(排,销售时点情报系统):如果销售时点情报系统> =N或者排> =N:返回假的如果销售时点情报系统在索尔:返回假的对于我在范围(伦恩(索尔)):如果销售时点情报系统==.索尔[我]+排-我或者销售时点情报系统==.索尔[我]-(排-我):返回假的返回真的def解决(销售时点情报系统,质量控制):质量控制- =1.索尔.追加(销售时点情报系统)如果质量控制==.0:返回真的#试一试对于我在范围(N):如果(已验证(N-质量控制,我)):如果(解决(我,质量控制)):返回真的索尔.流行音乐()质量控制+ =1.返回假的皇后区=㈡(输入().跳闸())N=皇后区索尔=[]对于我在范围(皇后区):如果(解决(我,N)):打印(索尔)索尔=[]
解决问题
现有用户?
加载时出现问题。。。
注意加载。。。
设置加载。。。