ImageVerifierCode 换一换
格式:DOCX , 页数:29 ,大小:29.42KB ,
资源ID:11210313      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/11210313.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(pascal递归算法noip竞赛材料.docx)为本站会员(b****8)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

pascal递归算法noip竞赛材料.docx

1、pascal递归算法noip竞赛材料信息学竞赛递归算法一个过程(或函数)直接或间接调用自己本身,这种过程(或函数)叫递归过程(或函数).递归程序包含递归和递推两个过程,这两个过程又都是根据一个递推公式进行的。一般来说,能够用递归解决的问题应该满足以下三个条件需要解决的问题可以化为一个或多个子问题来求解,而这些子问题的求解方法与原来的问题完全相同,只是在数量规模上不同;递归调用的次数必须是有限的;必须有结束递归的条件(边界条件)来终止递归。例1、楼梯共有N阶台阶,上楼可以以一步上一个台阶,也可以一步上二个台阶。编一个程序计算上N阶台阶,共有多少种走法? program stair(input,o

2、utput);var s,n:integer;function f(n:integer):integer; begin if n3 then f:=n else f:=f(n-1)+f(n-2); end;begin readln(n); s:=f(n); writeln(s=,s);end.例2、骨牌铺法有1*n的一个长方形,用一个11、12、13的骨牌铺满方格。例如当n=3时为13的方格。此时用11,12,13的骨牌铺满方格,共有四种铺法。图4.4.3列出了四种铺法。 输入n(0=n=30) 输出 铺法总数分析:这道题可以采用猜测法,从具体的n=1,2,3,.开始,列举出结果,根据列举的部

3、分结果进行猜测,推导出公式。这个猜测推导过程留给读者完成。问题是:这种方法中“猜”和“凑”的成分比较多,容易出错。我们不妨采用组合数学常用的待定系数进行归纳和推导。设推导公式如下:f(n)=a*f(n-1)+b*f(n-2)+c*f(n-3)+d*f(n-4)+.(a,b,c,d.是常系数)即1n的长方形的铺法由全部(a种)1(n-1)的长方形铺法总数加上全部(b种)1*(n-2)的长方形的铺法总数加上全部(c种)1*(n-3)的长方形的铺法总数.注意排除重复情况。(1)将n格分成1格和n-1格,计算f(n-1)的系数a。右端1格的铺法有一种(a)。显然,在一格中只有一种铺法,即f(n-1)的

4、系数a=1。(2)将n格分成2格和n-2格,计算f(n-2)的系数b。右端2格的铺法有两种(b)。由图可见,(b)的铺法包含在(a)的铺法中,而(c)的铺法不同于(a),因此f(n-2)的系数b=1。(3)将n格分成3格和n-3格,计算f(n-3)的系数c。右端3格的铺法有两种(图4.4.5)。由图可见,(d)(e)(f)的铺法都可以归结到1格或2格中去,只有1*3的铺法(g)属于新的,因此f(n-3)的系数c=1。将n格分成n-x格和x格(4=x=5)程序:var n:integer;function f(i:integer):longint;begin if i in1.2then f:=

5、ielse if i=3then f:=4else f:=f(I-1)+f(I-2)+f(I-3);end;begin readln(n); writeln(f(n);end.“铺砖问题”有推广价值。例如某人走n级的楼梯,每步可以走1级、2级或3级,走完n级楼梯共有多少种走法。这个问题的数学意义和解法与“铺砖问题”相同。例3: 划分问题 设s是一个具有n个元素的集合s=a1,a2,an,现将s集合划分成k个满足下列条件的子集合s1,s2,s3。; 1、si空; 2、sisj=空; 3、s1s2s3. sn=s (1=i,j=k,ij)则称s1,s2sn是集合s的一个划分,它相当于把集合s中的n

6、个元素放入k个无标号的盒子中,使得没有一个盒子为空,试确定n个元素的集合放入k个无标号盒的划分数s(n,k)【算法分析】: 例如S1,2,3,4,k3。细心的读者稍加分析后,不难得出S有6 种不同的划分方案,即划分数为6。其方案为 1,234 1,324 1,423 2,314 2,413 3,412 如果对于任意的S集合和k值,就不能凭籍直觉和经验计算划分数和枚举划分方案了。必须总结出一个数学规律:设n个元素a1an放入k个无标号盒的划分数为S(n,k)。在配置过程中, 有两种情况:1.设an是k个子集中的一个子集,于是把a1an-1划分为k1子集有S(n1,k1)个划分数;2.如果an不是

7、k个子集中的一个,即an必与其它的元素构成一个子集。首先把a1,an-1划分成k个子集,这共有S(n1,k)种划分方式。然后 再把an加入到k个子集中的一个子集中去,这有k种加入方式。对于每一种加入方式,都使集合划分为k个子集,因此由乘法原理知,划分数共有 k(n1,k)。 从上面的两种情况分析得出 S(n,k)S(n1,k1)+kS(n1,k) (n1,k1)下面,我们来确定s(n,k)的边界条件: 1.我们不可能把n个元素不放进任何一个集合中去,即(n,0)0;也不可能在不允许空盒的情况下把n个元素放进多于n的k个集合中去,即kn时S(n,k)0。 2.把n个元素放进一个集合或把n个元素放

8、进n个集合,方式数显然是1。即 S(n,1)=1 S(n,n)=1显然,通过上述分析可得出划分数S(n,k)的递归关系式: S(n,k)S(n1,k1)+kS(n1,k) (nk,k1) S(n,k)0 (nn)then s:=0 else if(k=1)or(k=n)then s:=1 else s:=s(n-1,k-1)+k*s(n-1,k); end; 相似题:m个相同的球放进n个相同的盒子(可以一个盒子放多个)有多少种不同的放法? m个相同的球放进n个不相同的盒子(可以一个盒子放多个)有多少种不同的放法?例4、简单的背包问题。设有一个背包,可以放入的重量为s。现有n件物品,重量分别为t

9、1 , t2 , t3 ti tn ,ti (1 in),均为正整数。从n件物品中挑选若干件,使得放入背包的重量之和正好为s【输入样例】 【输出样例】the number of object:5 number:1 weight:1total weight=10 number:3 weight: 21 6 2 7 5 number:4 weight:7【分析】 尝试构造函数snap(s,n)解决本题,分析情况如下: 、先取最后一个物品tn放入背包中,若tn=s,刚好放入包中, 问题得到解决并输出(n,tn). 、若tns,则不能放入包中,还得继续挑选;若还剩物品(即n1),问题即为从剩余的n-1

10、件物品中选取若干个,使得他们的重量和等于s,即snap(s,n)snap(s,n-1). 、若tn1),那么问题即可转换为从剩下的n-1件物品中选取若干件,使得他们的重量和等于包里剩下的可放入重量(s-tn),即:snap(s,n)snap(s,n-1);而选中的tn还要看snap(s-tn,n-1)是否有解,无解的话说明先取tn不合适,就要放弃tn,在剩余的物品中开始挑选,即有snap(s,n)snap(s,n-1).【参考程序】Const m=10;var t:array1.m of integer; x,y,i:integer; f:boolean;function sng(x:inte

11、ger):integer; 判断s-tn的三种情况 begin if x0 then sng:=1 else if x=0 then sng:=0 else sng:=-1; end;function snap(s,n:integer):boolean; 判断是否有解begin case sng(s-tn) of 0:begin writeln(number:n:4, weight:,tn:4); snap:=true; end; 1:begin if n1 then if snap(s-tn,n-1)=true then begin writeln(number:n:4, weight:,t

12、n:4); snap:=true; end else snap:=snap(s,n-1) else snap:=false end; -1:if n1 then snap:=snap(s,n-1) else snap:=false end;end;begin writeln(the number of object:);readln(y); writeln(total weight=); readln(x); for i:=1 to y do read(ti);readln;数据输入 f:=snap(x,y); x:weight, y:number if not(f) then writeln

13、(not found);end.例5、输出n个元素的无重复的全排列。N个元素有n!种不同排列。分析:1个元素直接输出;2个元素有两种排列,如(a b)(b a);3个元素以(a b c)为例,有: a b ca c bb a cb c ac b ac a b分析这些排列,一个简单的算法是:(1)a后随(b c)的所有排列(2)b后随(a c)的所有排列(3)c后随(b a)的所有排列上面(2)是将(1)中的a、b互换位置;上面(3)是将(1)中的a、c互换位置。这里意味着可以用循环的方法来重复执行“交换位置,后随剩余序列的所有的排列”;而对剩余序列可以再使用这个方法,这就成了递归调用,后随的元

14、素没有时,就到了递归的边界。对于n个元素a=(a1a2akan),设过程prem(a,k,n)是求a的第k到n个元素的全排列,设swap(a,k,I)是将a的第k个元素和第i个元素对换,i=k,n。program exp1_7;var a:string;k,n:integer;procedure swap(var a:string;k,i:integer);var t:char;begin t:=ak;ak:=ai;ai:=t;end;procedure perm(a:string;k,n:integer);var i:integer;beginif k=n then writeln(a)el

15、se for i:=k to n do begin swap(a,k,i);perm(a,k+1,n); endend;beginreadln(a);n:=length(a);perm(a,1,n);end.例6、 2的幂次方表示任何一个正整数都可以用2的幂次方表示.例如:137=27+23+20。同时约定次方用括号来表示,即ab可表示为a(b)。由此可知,137可表示为:2(7)+2(3)+2(0),进一步:7=22+2+20 (21用2表示);3=2+20;所以最后137可表示为:2(2(2)+2+2(0)+2(2+2(0)+2(0)。又如:1315=210+28+25+2+1;所以131

16、5最后可表示:2(2(2+2(0)+2)+2(2(2+2(0)+2(2(2)+2(0)+2+2(0)输入:正整数(n20000)输出:符合约定的n的0,2表示(在表示中不能有空格)【分析】:递归法2的幂次方由高幂向低幂分解1. 计算最接近n(小于n)的2的次幂e2en0(非第一项),则输出+;分析次幂ii=0,输出2(0); 递归边界i=1,输出2;i1,输出2(i的2幂次方表示) 递归准备分解下一项x1x1+1;nn-x;xx div 2;(无论n是否大于等于n)由此得出算法:procedure solve(n:word); var e,i,x1:byte; x:word;beginx163

17、84;e14; 21420000n do 计算最接近n(小于n)的x=2e begin xx div 2; ee-1 end;while x10; for ie downto 0 do 逐位分解2的幂次i begin if nx then begin 若能分解x=2i if x10 then write(+); 若当前是中间项 case i of 根据次幂i分解x的2幂次方表示 0: write(2(0); 1: write(2); else begin write(2(); solve(i); write() endelse end;case x1x1+1; nn-x 准备分解下一项x=2i

18、-1 end;then xx div 2 endforend;solve例7、求数字的乘积根。一个正整数的数字的乘积的定义是:这个整数中非零数字的乘积。例如,整数999的数字乘积为9*9*9,即729。729的数字乘积为7*2*9,即126。126的数字乘积为1*2*6,即12。12的数字乘积为1*2,即2。一个正整数的数字乘积根是这样得到的:反复取该整数的数字乘积,直到得到一位数字为止。例如,在上面的例子中数字的乘积根是2。编写一个程序,输入一个正整数(长度不超过200位数字),输出计算其数字乘积根的每一步结果。【分析】:每一步得到的乘积根比它的上一步的位数要小,显然存在递归过程,递归结束的

19、条件是乘积根的位数等于。具体程序编码如下:program ex5_17;var st:string;procedure init;begin writeln(please input:);readln(st);end;procedure make(ss:string);var a,b:array1.200 of integer;i,j,x,code:integer; w:string;begin fillchar(a,sizeof(a),0); for i:=1 to length(ss) do 取每一位数val(ssi,ai,code); fillchar(b,sizeof(b),0); x

20、:=1;b1:=1; for i:=1 to length(ss) do 每一位非0的数相乘 beginfor j:=1 to x do if ai0 then bj:=bj*ai;for j:=1 to x do 处理进位 begin bj+1:=bj+1+bj div 10; bj:=bj mod 10;end;if bx+10 then x:=x+1; end; ss:=; for i:=x downto 1 dobegin str(bi,w);ss:=ss+w;end; writeln(ss); if length(ss)1 then make(ss);end;begin init;输

21、入数据writeln(st);make(st); 递归处理readln;end.例8、输入N个字符,然后以倒序输出(用递归实现)。Program digui (input,output);Const n=8;Type mat=array1.n of char;Var i:integer;a:mat;Procedure print(i:integer);begin If i=n then write(ai) else begin print(i+1);write(ai); end;end;Beginfor i:=1 to n do readln(ai);i:=1; print(i); readl

22、n;End.例9、猴子选大王:有n只猴子选大王,先从头到尾至报数,报到的猴子退出,报至尾后,再从尾到头至报数,报到的猴子退出依次类推,当剩下两只猴子时,报的为大王。问若想当大王,应站在什么位置。【分析】:十只猴子编号,则出圈的次序为猴子编号:出圈次序:剩下和时,号猴子报为大王程序如下:program houzi(input,output);type arr=array1.100 of integer;var h:arr;I,j,m,n:integer;procedure num(var a:arr;var n,i:integer;m:integer);var f,k,s:integer;beginif n=3 then begin s:=0;k:=i mod 2;k 为表示从头到尾,k为表示从尾到头 case k of 1: for f:=1 to m do 正向报数if af0 then begin s:=s+1; if s=3 then begin s:=0;n:=n-1;af:=0; end;end; 0: for f:=m downto 1 do反向报数if af0 then begin s:=s+1;if s=3 then begin s:=0;n:=n-1;af:=0;end;end;end; i:=i+1;num(a,n,i,m);递归调用

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1