第5章-回溯法-习题
- 格式:ppt
- 大小:286.00 KB
- 文档页数:24
回溯法典型例题一、回溯法是啥呢?哎呀,回溯法就像是在一个迷宫里找路一样。
想象一下,你走进了一个超级复杂的迷宫,有好多岔路口。
回溯法就是当你走到一个岔路口发现不对的时候,就退回来,再试试其他的路。
它就像是你脑袋里的一个小导航,在你走错路的时候提醒你“哎呀,这条路不对,咱得回去重新选”。
比如说,在解决一些组合问题的时候,就像从一堆数字里选出满足某个条件的组合。
如果随便乱选,可能永远也找不到答案。
这时候回溯法就登场啦,它会有条理地去尝试各种可能的组合,一旦发现这个组合不行,就回到上一步,再换一种选法。
这就像是你在玩拼图,发现这块拼图放不进去,就换一块试试。
二、典型例题来喽1. 八皇后问题这可是回溯法里的经典呢。
在一个8×8的棋盘上放8个皇后,要求任何两个皇后都不能在同一行、同一列或者同一对角线上。
怎么用回溯法解决呢?我们就从第一行开始,试着放一个皇后,然后到第二行再放,但是要保证和前面放的皇后不冲突。
如果到某一行发现没有地方可以放了,那就回到上一行,重新调整上一行皇后的位置,再接着往下放。
这个过程就像是走迷宫的时候,发现前面是死胡同,就退回来换条路走。
2. 数独问题数独大家都玩过吧。
每个小九宫格、每行、每列都要填上 1 - 9这9个数字,而且不能重复。
用回溯法解决的时候,我们就从第一个空格开始,试着填一个数字,然后看这个数字是不是满足规则。
如果不满足,就换一个数字试试。
如果这个空格试遍了所有数字都不行,那就回到上一个空格,重新调整那个空格的数字,再接着往下填。
这就像我们在搭积木,发现这块积木放上去不稳,就换一块试试。
3. 全排列问题比如说给你几个数字,让你求出它们的全排列。
用回溯法的话,我们就从第一个数字开始,固定它,然后对剩下的数字求全排列。
当对剩下数字求全排列的时候,又可以把第二个数字固定,对后面的数字求全排列,这样一层一层下去。
如果发现排列不符合要求,就回溯到上一层,换一种排列方式。
这就像是在给小朋友排队,这个小朋友站这里不合适,就换个位置,然后重新给后面的小朋友排队。
回溯法习题汇总1.1 马拦过河卒源程序名knight.???(pas, c, cpp)可执行文件名knight.exe输入文件名knight.in输出文件名knight.out【问题描述】棋盘上A点有一个过河卒,需要走到目标B点。
卒行走的规则:可以向下、或者向右。
同时在棋盘上C点有一个对方的马,该马所在的点和所有跳跃一步可达的点称为对方马的控制点。
因此称之为“马拦过河卒”。
棋盘用坐标表示,A点(0, 0)、B点(n, m)(n, m为不超过15的整数),同样马的位置坐标是需要给出的。
现在要求你计算出卒从A点能够到达B点的路径的条数,假设马的位置是固定不动的,并不是卒走一步马走一步。
【输入】一行四个数据,分别表示B点坐标和马的坐标。
【输出】一个数据,表示所有的路径条数。
【样例】knight.in knight.out6 6 3 3 6【算法分析】从起点开始往下走(只有两个方向可以走),如果某个方向可以走再继续下一步,直到终点,此时计数。
最后输出所有的路径数。
这种方法可以找出所有可能走法,如果要输出这些走法的话这种方法最合适了,但是本题只要求输出总的路径的条数,当棋盘比较大时,本程序执行会超时,此时最好能找出相应的递推公式更合适,详见后面的递推章节。
1.2 出栈序列统计源程序名stack1.???(pas, c, cpp)可执行文件名stack1.exe输入文件名stack1.in输出文件名stack1.out【问题描述】栈是常用的一种数据结构,有n令元素在栈顶端一侧等待进栈,栈顶端另一侧是出栈序列。
你已经知道栈的操作有两·种:push和pop,前者是将一个元素进栈,后者是将栈顶元素弹出。
现在要使用这两种操作,由一个操作序列可以得到一系列的输出序列。
请你编程求出对于给定的n,计算并输出由操作数序列1,2,…,n,经过一系列操作可能得到的输出序列总数。
【输入】一个整数n(1<=n<=15)【输出】一个整数,即可能输出序列的总数目。
回溯法(Backtracking)是一种求解问题的算法思想,它通过尝试所有可能的解,在找到满足问题条件的解或者尝试完所有可能的解之后返回到之前的状态,进而继续尝试其他的可能解。
回溯法通常用递归的方式来实现,它在解决一个问题的过程中,搜索答案的空间树,通过对节点的选择和剪枝,来达到提高算法效率的目的。
洛谷(Luogu)是一个在线的OJ(Online Judge),提供了大量的题目,包括回溯问题的题目。
下面将介绍一些经典的洛谷回溯题目以及一些相关的参考内容。
1.“迷宫问题”:给定一个迷宫,求从起点到终点的路径。
迷宫通常用二维数组表示,其中0表示通路,1表示墙,求解路径可以使用回溯法的思想。
参考内容:《算法竞赛入门经典》第四章。
2.“N皇后问题”:将N个皇后放在一个NxN的棋盘上,使得任意两个皇后不在同一行、同一列或者同一对角线上。
可以使用回溯算法进行求解。
参考内容:《算法竞赛入门经典》第五章。
3.“数字拼图问题”:给定一个数字拼图,拼图由不同的数字组成,每个数字都有一个相应的可达区域,要求将数字拼图还原成正确的形状。
可以使用回溯算法进行求解。
参考内容:《LeetCode解题SQL报告》中的“digital_puzzle”题目。
4.“八皇后问题”:将8个皇后放在一个8x8的棋盘上,使得任意两个皇后不在同一行、同一列或者同一对角线上。
可以使用回溯算法进行求解。
参考内容:《数据结构与算法Python语言描述》第九章。
5.“组合总和”:给定一个无重复元素的数组和一个目标值,找出数组中所有可以使数字和为目标值的组合。
每个数字可以使用多次。
可以使用回溯算法进行求解。
参考内容:《LeetCode题解-组合总和系列》。
以上参考内容只是提供了一些经典的回溯问题以及相关的参考内容,对于想系统了解和学习回溯算法的人来说,可以通过搜索相关的书籍、博客或者教程来深入学习回溯算法的原理和实现。
此外,洛谷上还有许多其他类型的回溯问题可供练习,可以通过搜索洛谷的题目分类或者进行问题搜索来找到更多的回溯问题。
《算法及其分析》课后选择题答案及详解第1 章——概论1.下列关于算法的说法中正确的有()。
Ⅰ.求解某一类问题的算法是唯一的Ⅱ.算法必须在有限步操作之后停止Ⅲ.算法的每一步操作必须是明确的,不能有歧义或含义模糊Ⅳ.算法执行后一定产生确定的结果A.1个B.2个C.3个D.4个2.T(n)表示当输入规模为n时的算法效率,以下算法效率最优的是()。
A.T(n)=T(n-1)+1,T(1)=1B.T(n)=2nC.T(n)= T(n/2)+1,T(1)=1D.T(n)=3nlog2n答案解析:1.答:由于算法具有有穷性、确定性和输出性,因而Ⅱ、Ⅲ、Ⅳ正确,而解决某一类问题的算法不一定是唯一的。
答案为C。
2.答:选项A的时间复杂度为O(n)。
选项B的时间复杂度为O(n)。
选项C 的时间复杂度为O(log2n)。
选项D的时间复杂度为O(nlog2n)。
答案为C。
第3 章─分治法1.分治法的设计思想是将一个难以直接解决的大问题分割成规模较小的子问题,分别解决子问题,最后将子问题的解组合起来形成原问题的解。
这要求原问题和子问题()。
A.问题规模相同,问题性质相同B.问题规模相同,问题性质不同C.问题规模不同,问题性质相同D.问题规模不同,问题性质不同2.在寻找n个元素中第k小元素问题中,如快速排序算法思想,运用分治算法对n个元素进行划分,如何选择划分基准?下面()答案解释最合理。
A.随机选择一个元素作为划分基准B.取子序列的第一个元素作为划分基准C.用中位数的中位数方法寻找划分基准D.以上皆可行。
但不同方法,算法复杂度上界可能不同3.对于下列二分查找算法,以下正确的是()。
A.intbinarySearch(inta[],intn,int x){intlow=0,high=n-1;while(low<=high){intmid=(low+high)/2;if(x==a[mid])returnmid;if(x>a[mid])low=mid;elsehigh=mid;}return –1;}B.intbinarySearch(inta[],intn,int x) { intlow=0,high=n-1;while(low+1!=high){intmid=(low+high)/2;if(x>=a[mid])low=mid;elsehigh=mid;}if(x==a[low])returnlow;elsereturn –1;}C.intbinarySearch(inta[],intn,intx) { intlow=0,high=n-1;while(low<high-1){intmid=(low+high)/2;if(x<a[mid])high=mid;elselow=mid;}if(x==a[low])returnlow;elsereturn –1;}D.intbinarySearch(inta[],intn,int x) {if(n>0&&x>=a[0]){intlow= 0,high=n-1;while(low<high){intmid=(low+high+1)/2;if(x<a[mid])high=mid-1;elselow=mid;}if(x==a[low])returnlow;}return –1;}答案解析:1.答:C。
回溯法作业答案1. 旅行商问题(作业实验)设有n个城市,城市之间道路的长度均大于或等于0,还可能是∞(对应城市之间无交通线路)。
一个旅行商从某个城市出发,要经过每个城市一次且仅一次,最后回到出发的城市,问他如何走才能使他走的路线最短?分析:旅行商问题对应的解的元组为n元组,其中假设第一个城市为1,则n元组中未确定的为剩下n-1个城市,元组为(1,x2,…,x n),每个x i的取值为{2,…,n};约束条件为已经经过的城市不能再走,最后回到出发城市。
算法:INPUT: n个城市分别为{1,2,…n},城市之间路径长度的矩阵d[i][j] 。
OUTPUT: 从城市1出发的最短巡回旅行路线及长度。
1. for k =1 to n2. c[k] =13. end for4. k =2,L=0,MinL=∞5. while k≥26. while c[k]≤n-17. c[k] =c[k]+18. L=L+d[c[k-1]][c[k]]9. if c为合法的thenMinL=min{MinL,L}, p[]=c[]10. else if c是部分解then11. if L>=MinL then continue12. else k =k+113. endif14. endif15. end while16. L=L-d[c[k-1]][c[k]]17. c[k] =118. k =k-119. end while20. output MinL, p[]2. 邮票问题(作业实验选做)设有已知面额的邮票m种(假设一定有面值为1的邮票;如果没有,连续值就从最小面额的邮票面额值开始),每种有n张,问用总数不超过n张的邮票进行组合,能组合的邮票面额中可以连续的面额数最多有多少?例如:n=4 m=3v1=1 v2=2 v3=4最后的解为14。
分析:第一种思路:邮票问题是从m种邮票中选择n张邮票,求所有可能取得的面额,最后在确定最大连续面额的值。