递归与回溯算法
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
2.有些数据结构是递归定义的,采用递归的方法编写算法 既方便又有效。如单链表: Type node=^lnode lnode=record data:integer; next:node; end;
求一个不带头结点的单链表head的所有data域之和的 递归算法如下: Function sum(head:node):integer; Begin if head=nil then sum:=0 else sum:=head^.data+sum(head.next); 4 End;
3.问题的求解方法是递归的 例:整数划分问题(版本1) 为避免重复,记 n 1 2
1
n n n, 其中 n n n 1
k 2
k
设f(n,k)为把正整数n分成k份的分法,那么: 先考虑特殊情况: (1)f(n,1)=1 (n=n) (2)f(n,n)=1 (n=1+1+……+1) (3)当k>n时, f(n,k)=0 (4)若n1=1,则:
Function jiech(n:integer):longint; Begin if n=0 then jiech:=1 else jiech:=n*jiech(n-1); End;
2
爬楼梯时可以1次走1个台阶,也可以1次走2个台阶。对 于由n个台阶组成的楼梯,共有多少种不同的走法?
1个台阶:只有1种走法; 2个台阶:有两种走法;(1+1;2) N个台阶(n>2),记走法为f(n): 第1次走1个台阶,还剩(n-1)个台阶,走法为f(n-1); 第1次走2个台阶,还剩(n-2)个台阶,走法为f(n-2)。 所以,f(n)=f(n-1)+f(n-2)。 定义f(0)=1,则有: Function n 0 fib(n:integer):longint; 1 f (n) 1 n 1 Begin f (n 1) f (n 2) n 1 if(n=0)or(n=1)then fib:=1 else fib:=fib(n-1)+fib(n-2); 3 End;
枚举法的基本思想是根据提出的问题枚举所有可能状 态,并用问题给定的条件检验哪些是需要的,哪些是不 需要的。能使命题成立,即为其解。虽然枚举法本质上 属于搜索策略,但是它与后面讲的回溯法有所不同。因 为适用枚举法求解的问题必须满足两个条件: (1) 可预先确定每个状态的元素个数n; (2) 状态元素a1,a2,…,an的可能值为一个连续的值域。 设:ai1—状态元素ai 的最小值;aik—状态元素ai 的最大值 (1≤i≤n) , 即 a11≤a1≤a1k , a21≤a2≤a2k来自百度文库, ai1≤ai≤aik , …… , an1≤an≤ank for a1←a11 to a1k do fo a2←a21 to a2k do …………………… for ai←ai1 to aik do …………………… for an←an1 to ank do if 状态(a1,…,ai,…,an)满足检验条件 17 then 输出问题的解;
S E ND +MOR E MONEY
算式中的字符分别表示不同的阿拉 伯数字,找出能使等式成立的所有 数字组合。
直接枚举 S、E、N、D、M、O、R、Y分别从0..9范围内尝试每个取 值可能,共有108种组合需要判断 。
观察算式的形式,根据加法运算的特点可知: M=1,进一步分析,O=0,S=9, 因此只需枚举判断75种组合即可。
14
program hannuota; var n:integer; tot:longint; procedure hanoi(n:integer;s,t,d:char); begin if n>0 then begin hanoi(n-1,s,d,t); tot:=tot+1; writeln(s,’->’,d); hanoi(n-1,t,s,d); end; end; begin readln(n); tot:=0; hanoi(n,’A’,’B’,’C’); writeln(tot); end.
15
搜索算法 信息学奥赛的试题一般有两种类型: 1.简明的数学模型揭示问题本质。对于这一类试题,我们 尽量用解析法求解。 2.对给定的问题建立数学模型,或即使有一定的数学模型, 但采用数学方法解决有一定的困难。对于这一类试题,我 们只好用模拟或搜索求解。 尽管搜索的时间复杂度一般是指数级的,但在缺乏解决问 题的有效模型时,搜索却是一种行之有效的解决问题的基 本方法,而且使用搜索算法解决问题时,在实现过程中有 很大的优化空间。信息学奥赛中考察搜索算法,一是考察 选手算法运用能力,二是考察选手算法优化能力。 枚举法(穷举法) 回溯(深度优先搜索) 16 广度优先搜索
11
归并排序: 设归并排序的区间是R[low..high],则排序的步骤如下: (1)分解:将当前区间R[low..high]一分为二,即求 mid=(low+high)div 2;递归地对子区间R[low..mid]和 R[mid+1..high]进行继续分解。其终结条件是子区间长 度为1(因为一个记录的子表一定是有序表)。 (2)归并:与分解过程相反,将已排序的子区间R[low..mid] 和R[mid+1..high]归并为一个有序的区间R[low..high]。 procedure mergesort(var r:arr;low,high:integer); var mid:integer; begin if low<high then begin mid:=(low+high)div 2; mergesort(r,low,mid); mergesort(r,mid+1,high); merge(r,low,mid,high); end; 12 end;
6
整数划分问题(版本2) 在正整数n的所有不同的划分中,将最大加数n1不大于m 的划分个数记作q(n,m)。我们可以建立如下的递归关系。 (1) q(n,1)=1, n>=1; 当最大加数n1不大于1时,任何正整数n只有一种划分 形式,即: n=1+1+……+1。 (2) q(n,m)=q(n,n),m>=n; 最大加数n1实际上不能大于n。因此,q(1,m)=1。 (3) q(n,n)=1+q(n,n-1); 正整数n的划分有n1=n的划分和n1<=n-1的划分组成。 (4) q(n,m)=q(n,m-1)+q(n-m,m),n>m>1; n的最大加数n1不大于m的划分由n1=m的划分和 7 n1<=m-1的划分组成。
19
以4皇后为例:
20
回溯法的基本思想为: 在按某种搜索策略的搜索过程中,在 某种状态,继续往前搜索已经确定不会得 到正确答案的情况下,我们可以返回上一 搜索状态,去沿新的可能性继续搜索。要 回溯到上一状态,则说明我们在前进中的 状态必须保存下来,我们采用“栈”来存 放。
8
递归过程或函数直接(或间接)调用自身,但如果 仅有这些操作,那么将会由于无休止地调用而引起死循 环。因此一个正确的递归程序虽然每次调用的是相同的 子程序,但它的参数、输入数据等均有所变化,并且在 正常的情况下,随着调用的深入,必定会出现调用到某 一层时,不再执行调用而是终止函数的执行。
递归思路是把一个不能或不好直接求解的“大问题” 转化成一个或几个“小问题”来解决,再把这些“小问 题”进一步分解成更小的“小问题”来解决,如此分解, 直至每个“小问题”都可以直接解决。 递归分解不是随意地分解,要保证“大问题” 和“小问题”相似。 例:采用递归算法求实数数组A[0..n]中的最小值。
递归与回溯算法
1
递归的定义: 在定义一个过程或函数时出现调用本过程或本函数的成 分,称为递归。若调用自身,称为直接递归。若过程或 函数p调用过程或函数q,而q又调用p,则称为间接递归。 在程序设计中,使用递归技术往往使函数的定义和算法 的描述简洁且易于理解。 递归的使用: 1.定义是递归的
n0 1 n! n * (n 1)! n 0
9
算法1:设f(a,i)为数组元素a[0]..a[i]中的最小值。当i=0时, 有f(a,i)=a[0];假设f(a,i-1)已求出,则:
i a[0] 当 0时 f ( a, i ) min( f (a, i 1), a[i]) 其他情况
算法2:设f(i,j)为a[i]..a[j]中的最小值。将a[0]..a[n]看作一 个线性表,它可以分解成a[0]..a[i]和a[i+1]..a[n]两个子表, 分别求得各自的最小值x和y,较小者就是a[0]..a[n]中的最 小值。而求解子表中的最小值方法与总表相同,即再分 别把它们分成两个更小的子表,如此不断分解,直到表 中只有一个元素为止(该元素就是该表中的最小值)。
n n
2
k
n 1 ,且 n2 nk 1
5
其分法为f(n-1,k-1);
(5)若n1>1,则 (n1 1) (n2 1) (nk 1) n k 0
记 n1 n1 1, n2 n2 1, , k nk 1 n
' ' '
则1 n1 nk
' '
其分法为f(n-k,k)。
k 1或n k 1 0 n k f ( n, k ) k f (n 1, k 1) n 2 * k f (n 1, k 1) f (n k , k ) n 2 * k
10
function min(i,j:integer):real; var mid:integer; min1,min2:real; begin if i=j then min:=a[i] else begin mid:=(i+j) div 2; min1:=min(i,mid); min2:=min(mid+1,j); if min1<min2 then min:=min1 else min:=min2; end; end;
1 n 1或m 1 q(n, n) m n q(n, m) n 1 q(n, n 1) m q(n, m 1) q(n m, m) n m 1
Function q(n,m:integer):integer; Begin if(n<1)or(m<1) then exit(0); if(n=1)or(m=1) then exit(1); if n<m then exit(q(n,n)); if n=m then exit(q(n,m-1)+1); exit(q(n,m-1)+q(n-m,m)); End;{正整数n的划分数p(n)=q(n,n)。}
18
回溯法也是搜索算法中的一种控制策略,但与枚 举法不同的是,它是从初始状态出发,运用题目给出 的条件、规则,按照深度优先搜索的顺序扩展所有可 能情况,从中找出满足题意要求的解答。回溯法是求 解特殊型计数题或较复杂的枚举题中使用频率最高的 一种算法。 N皇后问题 在N*N的棋盘上放置N个皇后而彼此不受攻击(即在 棋盘的任一行,任一列和任一对角线上不能放置2个皇 后),编程求解所有的摆放方法。
汉诺塔问题: 有n个半径各不相同的圆盘,按半径从大到小,自 下而上依次套在A柱上,另外还有B、C两根空柱。要求 将A柱上的n个圆盘全部搬到C柱上去,每次只能搬动一 个盘子,且必须始终保持每根柱子上是小盘在上,大盘 在下。输出总共移动的次数及移动方案。
A
B
C
13
• 分析:在移动盘子的过程当中发现要搬动n个 盘子,必须先将前n-1个盘子从A柱搬到B柱 去,再将A柱上的最后一个盘子搬到C柱,最 后从B柱上将n-1个盘子搬到C柱去。搬动n个 盘子和搬动n-1个盘子时的方法是一样的,递 归处理。当只需搬一个盘子时,直接搬动, 不需要递归。