pascal中级教程第一章回溯.docVIP

  • 4
  • 0
  • 约7.49千字
  • 约 24页
  • 2017-02-01 发布于北京
  • 举报
第一章 回溯法 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.out 6 6 3 3 6 【算法分析】 从起点开始往下走(只有两个方向可以走),如果某个方向可以走再继续下一步,直到终点,此时计数。最后输出所有的路径数。这种方法可以找出所有可能走法,如果要输出这些走法的话这种方法最合适了,但是本题只要求输出总的路径的条数,当棋盘比较大时,本程序执行会超时,此时最好能找出相应的递推公式更合适,详见后面的递推章节。 1.2 出栈序列统计 1.3 算24点 1.4 冗余依赖 1.5 走迷宫 begin for i:=1 to 4 do{分别对4个点进行试探} begin 先记住当前点的位置,已走过的情况和走过的路; 如果第i个点(xl,y1)可以走,则走过去; 如果已达终点,则输出所走的路径并置有路可走的信息, 否则继续从新的点往下查找search(xl,y1,b1,p1); end; end; 【思考与提高】 该程序通过引进新的变量和数组来继续新的查找,如果不引进新的变量和数组,那么每一次返回时要将原来的值还原才行,如果那样,程序应如何修改?其实那样更加符合回溯的思想——换条路再试。这类问题也可以归为搜索的问题,如果m和n的值相对比较大,则解可能很多,若题目只要找到一条路就结束程序时,在程序的输出部分后面加上一个halt就行了。 有些情况很明显是无解的,如从起点到终点的矩形中有一行或一列都是为0的,明显道路不通,对于这种情况要很快地“剪掉”多余分枝得出结论,这就是搜索里所说的“剪枝”。从起点开始往下的一层层的结点,看起来如同树枝一样,对于其中的“枯枝”——明显无用的节点可以先行“剪掉”,从而提高搜索速度。 1.6 单向双轨道 如图所示l,某火车站有B,C两个调度站,左边入口A处有n辆火车等待进站(从左到右以a、b、c、d编号),右边是出口D,规定在这一段,火车从A进入经过B、C只能从左向右单向开,并且B、C调度站不限定所能停放的车辆数。 从文件输入n及n个小写字母的一个排列,该排列表示火车在出口D处形成的从左到右的火车编号序列。输出为一系列操作过程,每一行形如“h L R”的字母序列,其中h为火车编号,L为h车原先所在位置(位置都以A、B、C、D表示),R为新位置。或者输出‘NO’表示不能完成这样的调度。 【输入】 一个数n(1n27)及由n个小写字母组成的字符串。 【输出】 可以调度则输出最短的调度序列,不可以调度时则输出‘NO’。 【样例】 track.in track.out 3 c A B cba b A C a A D b C D c B D 【算法分析】 这是一道类似于栈的操作题目,只不过是有两个栈B和C可以操作,而对于A序列里的元素,既可以进入B,也可以进入C,或直接到D。解决问题可以从D序列出发反过来看,当前要到D的字符在哪里,如果在A,再看它前面有没有字符,如果有,先让它们进栈(B或C),否则直接到D;如果在B,看是否是栈顶元素,如果是,直接到D,否则将上面的字符进C;如果在C,看是否是栈顶元素,如果是,直接到D,否则无法进行操作,因为只能向右不能向左,这时要回溯。如果所有的情况都检测过,某个字符不能进行到D的操作,则输出无解信息。 由于A里的非直接进入D的字符可以进入B或C,可以跟二进制建立起对应关系,将所有情况列举一遍,再找出其中步骤最少的输出。 1.7 组合的输出 l 2 3 l 2 4 1 2 5 l 3 4 l 3

文档评论(0)

1亿VIP精品文档

相关文档