收藏 分享(赏)

奥赛竞赛辅导.doc

上传人:hskm5268 文档编号:8839298 上传时间:2019-07-14 格式:DOC 页数:31 大小:906.50KB
下载 相关 举报
奥赛竞赛辅导.doc_第1页
第1页 / 共31页
奥赛竞赛辅导.doc_第2页
第2页 / 共31页
奥赛竞赛辅导.doc_第3页
第3页 / 共31页
奥赛竞赛辅导.doc_第4页
第4页 / 共31页
奥赛竞赛辅导.doc_第5页
第5页 / 共31页
点击查看更多>>
资源描述

1、JSOI2005-2006 第一轮函授 A 组 A2-回溯、递归、递推 江苏省连云港市赣榆高级中学 仲晨第 1 页 共 31 页A 2 - 回溯、递归、递推 学习小结江苏省连云港市赣榆高级中学 仲晨http:/ “Myheimus Home“关键词:【JSOI2005-2006 第一轮函授 函授作业 A 组 第 2 次 回溯、递归、递推 学习小结】文件名:A2-回溯、递归、递推.doc 最后修改时间:2005 年 4 月 30日附带文件: N 皇后问题演示程序.exe (146 KB)文件大小:928.00 KB 共 31 页 ,合计 15297 字目录按 Ctrl鼠标单击 前往A 2 - 回

2、溯、递归、递推 学习小结 1一、导言(Introducation) .2二、关于回溯(About Backtracking) 4三递推与递归(Recursion) .7四、回溯递推递归 运用与优化 15五、高级本相关思考 .26JSOI2005-2006 第一轮函授 A 组 A2-回溯、递归、递推 江苏省连云港市赣榆高级中学 仲晨第 2 页 共 31 页一、导言(Introducation)作为导言,先说一下本文的写作思路与线索:本文虽为函授作业,但是我没有当作纯粹的作业来作。我尽量收集各类信息,上网收集资料,认真阅读相关书籍,然后结合高级本写成本文,在本文中涉及了许多内容,我将回溯、递归、递

3、推发散为很广阔的范围,为的是在这次函授之中能够尽量多的学到更多的东西。By the way,我也把本文作为一个自己的资料库,录入许多理解性的内容,作为总结与查询库。当然,决不能忘记要自己思考,学习小节,因此进行了很多题目算法的思考,我进行了思考研究,写出详解与勘误参考,水平有限,欢迎批评指教。本文线索就是回溯、递归、递推,我们围绕这三项进行讨论。回溯递归 递推一般实现方式正反方向有时可相互转化较简洁,要求数学规律性较强DFS穷举的优化版启发式搜索路径寻找图论/网络流数学问题:组合数学树、图、排序等问题分治、以大化小动态规划的实现DP=递归贪心回溯、递归、递推是计算机算法中基础内容,范围极其广泛

4、。为了描述清楚,根据我个人理解,特制下图:函授文件里要求思考一下七个问题,它们在本文中都将以专题形式叙述:JSOI2005-2006 第一轮函授 A 组 A2-回溯、递归、递推 江苏省连云港市赣榆高级中学 仲晨第 3 页 共 31 页回溯思想适合解决哪些问题?回溯思想在具体实现时,采用 递归与非递归的方法,各有什么优缺点?回溯与递归的关系怎样?递推与递归的关系怎样?递推的优点在哪儿?递推与动态规划的关系怎样?思考“栈”在递归、回溯中的作用?结合实例,分析它们的效率。回溯、递归、递推:基础而重要。我们应该努力理解其中的精髓,并把它的思想发挥到极致!下图是路径搜索的图像,美妙极了,就让它带领我们走

5、向回溯、递归、递推的世界吧!JSOI2005-2006 第一轮函授 A 组 A2-回溯、递归、递推 江苏省连云港市赣榆高级中学 仲晨第 4 页 共 31 页二、关于回溯(About Backtracking)回溯实质是 DFS ,也可以说 DFS 就是回溯(那些“高级”DFS 实质不再是回溯了!) ,属于静态规划。看多了动态规划,其实回溯使用范围更广,因此重要的多!回溯,首先需要“回”,才能“溯” ,这就关系到状态(State)的枚举与递进。对于一些简单的问题枚举也简单,不在说了。但是有些问题就不那么简单了,比如一些变化不一,状态联系较大的模型。对于这些问题,如果使用递归回溯较难,则可以使用数

6、学方法来枚举,就是一些可以递归回溯的题,为了判断、处理方便,也要使用数学枚举。例如:数字全排列、数字升序排列对于数字升序排列(n 个数字 1-n,排列为 m 位的数,并且后面的数字比前面的数字大) ,用回溯需要加判断,比较麻烦,而且如果需要使用这个排列进行其他的状态处理应用(如对应某个棋盘排列)就更麻烦了,所以我们可以使用从后向前找第一个小于后数的数字,将其加“1” ,再将其后数字升序排列的办法实现枚举。处理这个问题的办法是寻找变化规律。以上就是状态的处理问题。 回溯本是很简单的,有较固定的格式,但是, “标准”的回溯就是穷举!为了较好的时间效率和空间效率,我们需要进行优化,具体的表现就是剪枝

7、:状态判断分为:提前判断 和 当前状态判断。当前状态判断也就是判断当前回溯到了结点(note) ,判断是否满足题意,对于不同的题目,这个判断形式不同,如:不用判断(因为能回溯到结点就满足题意了) ,条件判断(判断其是否满足所有条件) ,最值判断(用于求最值的试题,比较是否大于 max 或小于 min)这些一般较简单,在此不表。专题问题:回溯思想适合解决哪些问题?回溯算法很大程度上类似穷举,或者 说回溯就是穷举的实现 形式之一。回溯也就是深度搜索,搜索到每个结点判断正确与最佳。因此,回溯算法适用于大规模状 态的逐一处理与寻找最佳状 态。JSOI2005-2006 第一轮函授 A 组 A2-回溯、

8、递归、递推 江苏省连云港市赣榆高级中学 仲晨第 5 页 共 31 页提前判断即剪枝,剪枝具有十分重要的作用,我们可以把回溯看作一个搜索树,当前状态判断剪掉的只是叶子(结点) ,但是剪枝顾名思义剪掉的是树枝(branch) 。这个对速度影响就大了!在很多情况下,我们已经找到了一组比较好的解。但是计算机仍然会义无返顾地去搜索比它更“劣”的其他解,搜索到后也只能回溯。为了避免出现这种情况,我们需要灵活地去定制回溯搜索的边界。剪枝的方法很多,主要有一下几种:1 调整法指通过比较子树来剪枝。这主要用于一些需要尝试许多一维可能状态时,而且这些一维状态有着明显的单调性或联系性(例如:如果某状态满足则小于它的

9、状态都满足题意,则可以不再扩展一个不满足状态的更大状态;又例:一个状态满足则其约数状态满足但不是最优,就可以不再扩展其约数状态。 ) ,这样就有可能实现剪枝,并且会有很大的作用(剪枝力度) 。特别对于单调状态,可以使用二分法将时间复杂度降到 之类的复杂度。Nlog22 范围判断(极端法 ,分枝定界法)通过判断之后的范围等条件是否满足来剪枝,例如埃及分数等题目。这个判断也十分灵活,有的可以通过比较是否有可能超过最值来剪枝,有的可以通过根据数学计算看是否有可能满足,还有的就是使用迭代加宽、迭代加深的 DFS 算法来作范围限制3 数学方法这就是使用数学判断方法来剪枝,同时也会运用调整法或极端法结合起

10、来使用,数学方法好多,需要就题论题,不表。例题 1 计算机网络连接要将 n(n=kx ,那么这个方案的总长度一定不小于 kx,那么,就不必要搜索下去了,直JSOI2005-2006 第一轮函授 A 组 A2-回溯、递归、递推 江苏省连云港市赣榆高级中学 仲晨第 6 页 共 31 页接换下一个结点继续搜索。路径 A1A 2A n 与路径 AnA n-1A 1 这两条路径是一个“正反”的关系,本质上是相同的,于是我们可以规定起点始的下标总是小于终点的下标假如路径的 A-B-C-D 的长度 A-C-B-D 的长度,那么包含 A-C-B-D 路径的路径的长度一定不是最短。有了上述的优化,题目就可以得到

11、很快的解决了。本题用的就是范围判断。剪枝并不是万能的,有些题目几乎没有剪枝方法,有些题目即使是将冗枝都剪除也会因为满足状态过多而超时。从而也推出回溯不是万能的(这是就时间空间而言,准确的说是:穷举理论上万能,但是时间空间表现不好) 。虽说如此,但是我们在没有十分好的其他方法或时间空间允许的条件下,首选回溯。剪枝剪掉的是时间,对于回溯的空间处理,可以使用更好的数据结构,例如 Hash 表(Hash Table)之类。回溯的使用形式:一般使用递归、模拟递归 (具体到递归,请参阅本文第三节。 )这里我写了递归框架,如下:Program 文件名;Const max = #;Type Datetype=

12、数据类型 VarStack: array 1max of datetype;Sum:longint;sum 是总可能数或最值Procedure try(depth:integer);beginif stackdepth-1是目标状态 thenbegininc(sum);处理结果;输出或判断是否是最值exit;end;for i:=1 to 可能下一状态数 dobegin判断,剪枝;stackdepth:=可能状态 i ;try(depth+1);end;end;BeginSum:=0;Init;初始化Try(1);输出 sum;End.回溯简单而复杂,所以也没有什么固定的格式,之所以写下这个蹩

13、足的框架,是为了理解回溯的层次递归。至于模拟递归,新高级本上讲的很清楚了,关系到栈的使用,在第六个专题中将涉及。回到本节开头,回溯就是 DFS,DFS 就是回溯。DFS 的算法好多好多,并且优化形式不一,在本文JSOI2005-2006 第一轮函授 A 组 A2-回溯、递归、递推 江苏省连云港市赣榆高级中学 仲晨第 7 页 共 31 页第四节中将对于常用的方法进行学习。也是由于回溯的思想还算简单,本节就到此为止了,下面需要结合递归来探讨。JSOI2005-2006 第一轮函授 A 组 A2-回溯、递归、递推 江苏省连云港市赣榆高级中学 仲晨第 8 页 共 31 页三递推与递归(Recursio

14、n)递推要求数据关系较密切,有明确的公式和单调性,也就因此用途比较狭窄,但是绝不意味这在竞赛中没有用处,下面的例子就是一个很好的例子:K上升段问题 描述: 对于自然数 1n 的一个排列 A1N 可以划分 为若干个单调递增序列。每个单调递增序列由连续元素 Asted组成,且满足以下条件:1 Aed+1;例如:排列 1 2 4 5 6 3 9 10 7 8 可划分为 3 个单调递增序列 1 2 3 4 5;3 9 10 ;7 8 ; 所以我们称这是一个 3 上升段序列 。现在给定 n 和 k , 求出 n 的全排列中的,k 上升段序列 的个数。输 入格式: 输入仅有 1 行,包含两个数 n, k(

15、1 =j) fi-1,j+fi,j-i (else)s:=f(k,n-k)本题可以用循环来实现递推,也可以考虑用递归求解。主过程见下一页:可以看出,方案一的程序较为冗长,消耗栈空间较大;而方案二较为简洁明了,所用的栈空间也较小,效率较高。因此,使用递归算法也有一个优化问题。算法的简洁与否直接制约了程序的可行性和效率。JSOI2005-2006 第一轮函授 A 组 A2-回溯、递归、递推 江苏省连云港市赣榆高级中学 仲晨第 12 页 共 31 页递归使一些复杂的问题处理起来简单明了,尤其在学习算法设计、数据结构时更能体会到这一点。但是,递归在每一次执行时都要为局部变量、返回地址分配栈空间,这就降

16、低了运行效率,也限制了递归的深度。因此,在必要的时候可以只使用递归的思想来求解,而程序则转用非递归的方式书写,关于递归与非递归的转化,参见新高级本吧。 方案一:Procedure work(I,j:longint; var s:longint);Var t:longint;BeginIf (i=1) or (j=1) then s:=1Else if (i=0) or (j=0) then s:=0Else beginif (j mod i=0) and (j div i=1) then beginwork(i-1,j,s);t:=s;work(i,j-1,s);s:=s+t+1;endels

17、e if (i=j) then work(i-1,j)else beginwork(i-1,j,s);t:=s;work(I,j-1,s);s:=s+t;end; End;方案二:procedure search(v,w,last:byte);var i:byte;beginif w=0 then inc(count)elseif w=1 thenif v=last then search(0,0,0) elseelse for i:=last to v-1 do search(v-i,w-1,i);end;JSOI2005-2006 第一轮函授 A 组 A2-回溯、递归、递推 江苏省连云港市

18、赣榆高级中学 仲晨第 13 页 共 31 页专题问题: 栈(对不起,这里使用了一点别人的冬冬,第 1 节概述是我找的资料,其他是我自己的)1 概述栈(Stack)是一种特殊的线性表。我们常举的例子是:可以把食堂里冼净的一摞碗看作一个栈。在通常情况下,最先冼净的碗总是放在最底下,后冼净的碗总是摞在最顶上。而在使用时,却是从顶上拿取,也就是说,后冼的先取用,后摞上的先取用。好果我们把冼净的碗“摞上”称为进栈,把“取用碗”称为出栈,那么,上例的特点是:后进栈的先出栈。然而,摞起来的碗实际上是一个表,只不过“进栈”和“出栈” ,或者说,元素的插入和删除是在表的一端进行而已。一般而言,栈是一个线性表,其

19、所有的插入和删除均是限定在表的一端进行,允许插入和删除的一端称栈顶(Top),不允许插入和删除的一端称栈底(Bottom)。若给定一个栈 S=(a 1, a2,a 3,a n) ,则称a1 为栈底元素, an 为栈顶元素,元素 ai 位于元素 ai-1 之上。栈中元素按 a1, a2,a 3,a n 的次序进栈,如果从这个栈中取出所有的元素,则出栈次序为 an, an-1,a 1 。也就是说,栈中元素的进出是按后进先出的原则进行,这是栈结构的重要特征。因此栈又称为后进先出(LIFOLast In First Out) 表。我们常用一个图来形象地表示栈,其形式如右图:通常,对栈进行的运算主要有以

20、下几种:(1) 往栈顶加入一个新元素,称进栈;(2) 删除栈顶元素,称退栈;(3) 查看当前的栈顶元素,称出栈。此外,在使用栈之前,首先需要建立一个空栈,称建栈;在使用栈的过程中,还要不断测试栈是否为空或已满,称为测试栈。2栈的存储结构JSOI2005-2006 第一轮函授 A 组 A2-回溯、递归、递推 江苏省连云港市赣榆高级中学 仲晨第 14 页 共 31 页栈是一种线性表,在计算机中用向量作为栈的存储结构最为简单。因此,当用编程语言写程序时,用一维数组来建栈十分方便。例如,设一维数组 STACK 1 . . n 表示一个栈,其中 n 为栈的容量,即可存放元素的最大个数。栈的第一个元素,或

21、称栈底元素,是存放在 STACK1处,第二个元素存放在STACK2处,第 i 个元素存放在 STACK i 处。另外,由于栈顶元素经常变动,需要设置一个指针变量top,用来指示栈顶当前位置,栈中没有元素即栈空时,令 top=0,当 top=n 时,表示栈满。3“栈”在递归、回溯中的作用?栈是事实上的递归、回溯使用方法,我们使用递归时就是利用了栈的原理:每一层保存当前的状态,然后继续递归到下一层。当我们理解了栈的使用与递归后,我们可以使用模拟的栈(以我们自己的原则,创建一个栈,并由我们自己来维护)来实现所有的递归、回溯问题,尽管使用递归很简洁方便,但是对于大型程序、层数众多的程序,我们需要模拟栈

22、来实现。模拟栈实现回溯的就叫做模拟回溯。栈的表象, 数据结构的演示程序十分真切的,我就不想冗述- 我截了两幅图,在这里代替了。JSOI2005-2006 第一轮函授 A 组 A2-回溯、递归、递推 江苏省连云港市赣榆高级中学 仲晨第 15 页 共 31 页栈溢出是递归、回溯使用时的大问题,特别是对于数据大的题目,我们应当特别注意。JSOI2005-2006 第一轮函授 A 组 A2-回溯、递归、递推 江苏省连云港市赣榆高级中学 仲晨第 16 页 共 31 页四、回溯递推递归 运用与优化在本节主要是回溯、递推、递归的深入讨论和优化。下面对一个经典问题做一下讨论:八皇后之递归算法、回溯算法我在网上

23、偶尔找到了一个 N 皇后的演示程序,做的非常好,大家共享,共同进步。【问题描述】在一个格子的棋盘上,要布局八个皇后,条件是不能出现两个皇后在同一行或同一列或同一斜线的情况,以防“相互攻击”,请问共有多少种合理的布局方式,每一种布局的具体情况如何?右上图是 4 皇后问题规则示意右下图是 8 皇后问题的第一个解【分析】显然问题的键在于如何判定某个皇后所在的行、列、斜线上是否有别的皇后;可以从矩阵的特点上找到规律,如果在同一行,则行号相同;如果在同一列上,则列号相同;如果同在斜线上的行列值之和相同;如果同在 斜线上的行列值之差相同;如果斜线不分方向,则同一斜线上两皇后的行号之差的绝对值与列号之差的绝

24、对值相同。从下图可以验证上面的说法: 对于一组布局我们可以用一个一维数组来表示:X:ARRAY 18 OF INTEGER;XI的下标 I 表示第 I 个皇后在棋盘的第 I 行,XI的内容表示在第 I行的第 XI列,例如:X3=5 就表示第 3 个皇后在第 3 行的第 5 列。在这种方式下,要表示两个皇后 A和 B 不在同一列或斜线上的条件可以描述为:XAABS(XA-XB)A 和 B 分别表示两个皇后的行号JSOI2005-2006 第一轮函授 A 组 A2-回溯、递归、递推 江苏省连云港市赣榆高级中学 仲晨第 17 页 共 31 页JSOI2005-2006 第一轮函授 A 组 A2-回溯

25、、递归、递推 江苏省连云港市赣榆高级中学 仲晨第 18 页 共 31 页Program Qn(Input,Output);递归算法const n=8;varcont,i:integer;a:array1n of byte;存放正确的一组解c:array1n of boolean;存放某一列放皇后的情况,用于判断是否有同列的情况l:array1-nn-1 of boolean;存放某一斜线上放皇后的情况,用于判断是否有同斜线的情况;斜线的方向为r:array22*n of boolean;存放某一斜线上放皇后的情况,用于判断是否有同斜线的情况;斜线的方向为procedure pr;vari:in

26、teger;beginfor i:=1 to n do write(ai:4);inc(cont);writeln( cont=,cont);end;procedure try(i:integer);varj:integer;procedure erase(i:integer);begincj:=true;li-j:=true;ri+j:=true;end;beginfor j:=1 to n dobeginif cj and li-j and ri+j thenbeginai:=j;cj:=false;li-j:=false;ri+j:=false;if i0 dobeginxk:=xk+1

27、;while (xkf2 return ai, j + f1; else return ai, j + f2;显而易见,这个算法就是最简单的搜索算法。时间复杂度为 2n,明显是会超时的。分析一下搜索的过程,实际上,很多调用都是不必要的,也就是把产生过的最优状态,又产生了一次。为了避免浪费,JSOI2005-2006 第一轮函授 A 组 A2-回溯、递归、递推 江苏省连云港市赣榆高级中学 仲晨第 20 页 共 31 页很显然,我们存放一个 opt 数组:Opti, j - 每产生一个 f(i, j),将 f(i, j)的值放入 opt 中,以后再次调用到 f(i, j)的时候,直接从opti,

28、j来取就可以了。于是动态规划的状态转移方程被直观地表示出来了,这样节省了思维的难度,减少了编程的技巧,而运行时间只是相差常数的复杂度,而且在相当多的情况下,递归算法能更好地避免浪费,如题目(巧切蛋糕) ,在比赛中是非常实用的。总结 记忆化搜索是对动态规划状态转移方程的直观表示。本质上来说,它仍然是用搜索算法的核心,只不过使用“记录求过的状态”的办法,来避免重复搜索,这样,记忆化搜索的每一步,也可以对应到动态规划算法中去。记忆化搜索有优化方便、调试容易、思维直观的优点,但是效率上比循环的动态规划差一个常数,但是时间和空间复杂度是同一数量级的(尽管空间上也差一个常数,那就是堆栈空间) 。当 n 比

29、较小的时候,我们可以忽略这个常数,从而记忆化搜索可以和动态规划达到完全相同的效果。估价函数启发式搜索的主要目标是使用一个函数去判断所有状态的“好坏” ,以提高搜索找到解的效率。通常,估价函数表示成一个函数或是一个状态,这个函数叫做“估价函数” 。对于相同的题目,有时有不同的估价函数。直观地看,越优秀的估价函数,搜索的速度就越快。当然,估价函数不一定是十全十美的(否则就是贪心法了) ,总归会对某些状态予以不太准确的评价,于是,评价值(函数返回值)和实际好坏的差异越小,估价函数就越优秀。注意!一个人脑看起来似乎非常非常弱智甚至笑它太傻的估价函数可能收到非常大的效果,也许搜索算法的运行时间(或空间)

30、会缩小 100000 倍甚至更多。对于启发式搜索的应用,有以下几点:(1)启发式剪枝最简单也是最常用的启发式搜索是利用估价函数来剪枝。假设我们的问题是要求找最小总花费。对于一个可接受的估价函数,当前花费是 A,启发函数返回了 B,当前子问的最优解是 A+B。如果找到的一个解一个花费是 C,C4 5 60 8 7 7 8 0估价函数返回的值为:2 + 1 + 1 + 0 + 1 + 1 + 2 + 0 + 2 = 10返回值越小,说明该状态离目标状态最近。虽然这个启发函数不完美,误判的情况很多,但是它能够非常大地提高搜索效率,在 n 比较大的时候,有助于在非常短的时间内找到可行解,并且可以用收缩

31、节点的办法,找出更优的可行解。小结 启发式搜索并不是完美的搜索。无论怎样的启发函数,都会存在一定的缺陷,但是缺陷并不影JSOI2005-2006 第一轮函授 A 组 A2-回溯、递归、递推 江苏省连云港市赣榆高级中学 仲晨第 22 页 共 31 页响搜索效率的提高。竞赛和实际问题中,越来越多的问题,不要求最优解,只要求可行解,但是往往找这些可行解相当的困难,此时往往就需要启发函数来帮忙。 启发函数会在极其短的时间内找到一个较优解,接着,我们可以根据这个解进行限界甚至收缩,得到满意的结果。众所周知,对于某些动态规划题,对状态转移的设计要求是非常高的。往往用 o(log2n)的时间复杂度实现状态的

32、转移,与用 o(n)的时间复杂度实现状态转移效率有天壤之别。这种优化技巧很明显可以用在记忆化的 DFS 上,而且往往收到很好的效果,因为记忆化 dfs 与循环实现的动态规划只有常数上的差别,而对于某些状态不完全的动态规划,记忆化搜索的效率甚至好过循环。其实在搜索算法中,状态转移上的优化(也就是扩展结点上的优化) ,在优化中仍然能起很大的作用,只是大家总是忙于探索如何减少搜索算法的浪费,忽略了这一点。例题 6 最大机 (题目来源:ACM CEERC 2003 Problem I)分析 对于两个排序机 ai和 aj,如果 ai.endvex 在 aj.startvex 和 aj.endvex 之间

33、,我们就把它们连一条边,样例如下图所示:很明显,我们所要求的排序机数量,就是 ap.startvex=1, aq.startvex=n 的最短路径。因为这个最短路径非常特殊,所有的边权都是 1,所以我们采取用宽度优先搜索的办法来实现。粗略地看一下,BFS 的时间复杂度是 o(m),是完全可以承受的,但是不能忽略的是,如果我们用Dijkstra 式的扩展方式,那么,扩展结点的复杂度是 o(m),对于每一个结点都扩展一次,就是 m2。而 m 最大到 500000,m2 的算法是必然行不通的。但是不是这样就可以否定 DFS 算法呢?答案是否定的。紧扣着产生结点的规律,又因为 nj 的时候,aj才可以

34、和ai相连,所以 hash 单元里也可以是一棵以结点号为关键字的二叉排序树,以提高检索速度。对于扩展结点时的扫描,也可以再开一个 hash 表来映射结点,这样两个不同的 hash 表进行映射,大大增加了效率,算法时间复杂度接近 o(m*f(x),f(x)为 hash 查找的平均时间。我们再看看动态规划算法。一般的动态规划也是 m2,如果用二叉排序树或二叉平衡树(尽管那很烦琐)来实现,可以优化到 mlog2m,但是 log2m 比 f(x)要大的多:500000 个元素映射到 50000个 hash 单元中,平均每个单元只有 10 个元素,加上二叉排序树的复杂度是 log2(k),这个数值大约是

35、3.3,而 log2m 的数值大约是 18.9。两者效率相差约 5.7 倍。小结 搜索的时间的确主要耗费在检查状态树上,但是当结点非常多的时候,我们仍然有必要好好考虑应该如何优化结点的扩展。毕竟每转移一次状态耗费 n 的时间,在 n 很大的时候是得不偿失的。状态扩展的本质是查找。当状态转移数非常数时,可以考虑排序+二分查找,也可以构建索引、散列或者是二叉排序树,也可以将这几个数据结构进行有机结合,例如索引元素是散列,散列解决冲突用排序树。每每遇到这个种类的问题,我们需要充分利用数据结构上的技巧,把状态转移时间降到最低。化整为零式的拆点方法看一个很简单的例子:(虽然这里是 BFS 问题,不属于本

36、文讨论范围,我还是写在这里来研究搜索的优化问题)例题 7 迷宫问题。有 n*m 的方格,可以向相邻方向移动,求从(1,1)点到(n,m)点的最短路径。这是一个最短路径问题,熟悉 bfs 的同学一定会用 o(n*m)的算法来实现,当然,这个题也可以用Dijkstra 算法来实现。分析一下复杂度:有 n2 个点,有 4*n2 条边,Dijkstra 算法的标准复杂度是 o(16*n4),优化后可以为 o(n2log2(n)。同样的,如果我们这个迷宫改变一下,有的通过代价是 2,有的通过代价是 1,那么,似乎第 1 种简单 bfs 的办法就行不通了。第二种 Dijkstra 仍然行的通,但是时间效率

37、并不理想。于是,从把复杂问题简单化的角度考虑,我们可以尝试着把复杂结点拆成简单结点来处理。解决这一类问题, “拆点”其实是一种高级的算法技巧,需要比较高的问题分析能。上例拆开的,仅仅JSOI2005-2006 第一轮函授 A 组 A2-回溯、递归、递推 江苏省连云港市赣榆高级中学 仲晨第 24 页 共 31 页是最简单意义上的拆结点,而且只对固定的结点拆成了两个,但是,它体现了拆点法的最本质思想。拆结点将非常规问题常规化。我们可以作一个比较,对于上例,n=200,所以 Dijkstra 算法也是能通过的,当然,为了扫描节约时间,还必须把图建成邻接表的形式,且需要用菲波那契堆来实现算法,编程复杂

38、度是可想而知的。而拆点的 bfs 方法,虽然思维难度稍微大一些,但是不但提高了效率,还简化了编程复杂度,甚至可以直接在 bfs 的基本模块上修改。拆点算法扩大了算法的常数项,但是换来的,往往比想出一种复杂高效算法更快、更巧、更省力。我写到这里可是累得够戗,唉,接着来!在这里再讨论一个经典问题背包问题背包问题一般是这样描述的:设 n 个重量为(W1,W2,.Wn)的物品和一个载重为 S 的背包,将物品的一部分 xi 放进背包中的利润是 Pixi,问如何选择物品的种类和数量,使得背包装满而获得最大的利润?另有一简化版本说:设有一个背包可以放入的物品重量为 S,现有 n 件物品,重量分别为W1,W2

39、,.Wn。问能否从这 n 件物品中选择若干件放入此背包,使得放入的重量之和正好为 S。前提贪心法它是一种多步决策法,它总是作出在当前看来是最好的选择,它的考虑不是从整体出发,而只是某种意义上的局部最优,这样贪心法不能对所有问题达到整体最优解,但是对相当范围的许多问题都能够产生整体最优解。动态规划它是将问题进行逐步的划分来缩小问题的规模,直到可以求出子问题的解为止。分划子问题后,对应的子问题中含有大量的重复,这样就将重复地求解;在第一次遇到重复时把它解决,并将解保存起来,以备后面引用。动态规划法常用来求一个问题在某种意义下的最优解。递归下降例题 8 用录音带录音农场主约翰最喜欢的爱好是制作一个

40、Bessie 喜欢的音乐合集磁带以便它在产奶时听。Bessie 的产奶量取决于它产奶时所听的歌曲。已知一组歌曲(每首歌都由一对整数此曲的长度(以秒计),听该首歌时的产奶量来表示)以及给挤奶的总时间。找到这样一组歌曲的集合,使得歌曲的总长度不超过给 Bessie 挤奶的总时间且使JSOI2005-2006 第一轮函授 A 组 A2-回溯、递归、递推 江苏省连云港市赣榆高级中学 仲晨第 25 页 共 31 页Bessie 的产奶量达到最大。抽象描述已知一组物品-每个都有其尺寸和值(比如,重量),以及可用的总空间。找到这样一个集合,使得该集合的值的和最大,且其尺寸的和受某些限制所约束。集合中任何一个

41、特定的项目的总数目/尺寸不能超过它的可利用率。解题想法视其为背包问题的一般方法是一个容量受限的背包使得放入其中的物品的值达到最大。以上述问题为例,Bessie 产奶时听的音乐带就是“背包”,而那些歌就是“放入背包中的物品”。三个背包问题背包问题有三种形式:小数背包问题允许将小数表示的物品放入背包中的是小数背包问题。举例来说,如果物品是原油、飞机燃料、煤油而你的背包是一只水桶,取 0.473 升的原油,0,263 升的飞机燃料和 0,264 升的煤油就是有意义的。这是形式最简单的要解决的背包问题。小数背包问题是三者中最简单的,其贪婪解法如下:找到“值密度”(物品值/尺寸)最大的物品如果总容量仍就

42、超过物品的可利用率,把所有满足条件的物品放入背包中,然后反复执行。如果总容量少于物品的可利用率,尽可能多的使用可用空间,然后终止。由于这个算法必须先按照值密度把物品分类,然后以降序将它们放入背包,直至容量用完,该算法以 N log N 级运行。通常简单些的方法不是将它们分类,而是不停地找每次不用的最大值密度,这种算法的时间复杂度是 O(N 2) 。注意:对于这类问题,因为你可以做一个微小的变换使得所有的物品尺寸大小为一,且原始尺寸大小和可利用率(当然用原始尺寸大小除值)的乘积就是总容量,同时有尺寸和可利用率是很少见的。延伸:在这种情况下,物品的值和可利用率可以是实数。用这种算法处理有小数的尺寸

43、大小也不是问题。整数背包问题JSOI2005-2006 第一轮函授 A 组 A2-回溯、递归、递推 江苏省连云港市赣榆高级中学 仲晨第 26 页 共 31 页在整数背包问题中,只有完整的物品能放入背包里。此形式的一个例子就是:部分的曲子不允许放入包中。这个问题有点难度,但是如果背包足够小,使用动态规划,它还是可解的。依据背包大小的最大值设计动态的程序。刷新用来表示大小为 S 的物品的数组,颠倒其次序,看将当前物品放入大小为 K 的背包中所产生的集合是否比当前最好的大小为 K+S 的背包更符合条件。这个算法运行 K*N 次,其中 K 是背包的大小,N 是物品的可利用率义之和。如果背包太大了以至于

44、无法分配此数组,递归下降是一种选择,即这个问题是 NP 完全的(给定I 上的一个语言 L,如果有一架非确定图灵机 M 和一个多项式 P(n),对任何 I 上的长度为 n 的串 w,M都可以在 P(n)步内确定是否接受 w,则称 L 是非确定图灵机下多项式时间复杂性问题,简记为 NP 问题/语言。若 L 是属于 NP 的,且对 NP 中的每一个语言 L,都存在一个从 L至 L 的多项式时间转化,我们说 L 是 NP 完整的。- 译者)。当然,递归下降在以小的物品填充的大背包情况下可以运行相当长的一段时间。延伸:小数的值不是问题;数组可以用实数数组来代替整数数组。小数的可利用率并不影响什么,在没有

45、大量损失的条件下,缩短数字(如果你有 3,5 个物品,你可以仅用 3)。小数的尺寸是个讨厌的东西,它使得问题递归下降。如果尺寸都相同,问题就能贪婪地解开,在下降的值排序中选择物品,直到背包满为止。如果值都是 1.0,同样地使用贪心法,在上升的尺寸大小排序中选择物品,直到背包满为止。多重背包问题在多重背包问题中,需被填充的背包多于一个。如果允许有小数的物品放入,也就等于有一个大的背包,其容量相当于所有可用背包的和。因此,此术语只用来指多重整数背包的情况。对于任何大小的多重背包,状态空间太大了以至于无法使用从整数背包算法中来的 DP 解法。于是递归下降是解决这个问题的方法。延伸:用递归下降,通常扩

46、展就简单了。小数的尺寸和值就不是问题了,同样地值的计算功能也不是问JSOI2005-2006 第一轮函授 A 组 A2-回溯、递归、递推 江苏省连云港市赣榆高级中学 仲晨第 27 页 共 31 页题。如果值都是同一个,那么如果能被放入所有背包中的物品的最大值是 n,则存在使用 n 个最小物品的解法。它能大大减少查找时间。例题 9 分数膨胀1998 USACO National Championship你正试图设计一个有最高分数(10,000) 的比赛。已知比赛长度,一组问题,问题的长度以及每个问题的分值,计算满足长度约束的最高分数的比赛。分析:这是一个整数背包问题,比赛是背包,尺寸是问题的长度

47、,值是分数值。背包(比赛)尺寸的限制是其足够小使得解法在存储器中运行。例题 10 篱笆栏1999 USACO Spring Open农场主约翰准备在他的领地建一圈篱笆。他已装好了柱子,所以他知道所要的围栏长度。当地的木材店有各种长度的木板(至多 50 个)。已知木材店木板的长度,约翰要的围栏长度,计算约翰建篱笆所用的围栏最大值。分析:这是个多重背包问题,木材店的木板是背包,物品是约翰用的围栏。物品的尺寸就是长度,值是一。由于值都是一,如果存在用任意 K 个围栏的解法,则有用 K 个最小围栏的解法。例题 11 装满你的油箱你在 Beaver 郡中部一百英里有一个加油站的城市中,想将你的油箱装满好

48、能到达 Rita Blanca。幸运地是,这个小镇有两三个加油站,但它们的油都好像要用光了。已知每个加油站的油价,每个加油站的油量,计算为了花最少的钱,应该从每个加油站买多少汽油。分析:这是一个小数背包问题,背包是油箱,物品是汽油。JSOI2005-2006 第一轮函授 A 组 A2-回溯、递归、递推 江苏省连云港市赣榆高级中学 仲晨第 28 页 共 31 页五、高级本相关思考说句实话,新高级本习题集上面的详解少了些,不过也是好事,我们应该运用各种书籍和网络资助学习。全国青少年信息学奥林匹克联赛培训教材(中学高级本)质量不错,只有一个地方让我思考了好一会儿(我笨?),就是在 Page 31 上【例 210】B 光滑数分析中的递归关系:f (b,x1,x2) f ( b,(x1-1) div primeb1,x2 div primeb)我标出的红色部分是什么意思呢?我后来想,可能是为了实现取 不小于 x1 div primeb的最小整数因为当 x1 mod primeb0 时, (x1-1) div prime1+1 x1 div p

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 企业管理 > 管理学资料

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报