信息学初级教程(8)

2019-01-19 17:21

(5)1 1 (6) * (7) * (8) ******* 22 22 * * *** *** *** 333 333 * * ***** ** ** 4444 4444 * * * * * * 555555555 * * ** ** ** ** * * *** *** *** *** * ******* (9) 1 2 3 4 5 6 7 (10) 1 2 4 7 11 16 22 (11) 1 8 9 10 11 12 13 3 5 8 12 17 23 121 14 15 16 17 18 6 9 13 18 24 12321 19 20 21 22 10 14 19 25 1234321 23 24 25 15 20 26 12321 26 27 21 27 121 28 28 1 (12) 1 (13) 1 2 3 4 5 (14) 1 212 16 17 18 19 6 6 2

32123 15 24 25 20 7 10 7 3 4321234 14 23 22 21 8 13 11 8 4 32123 13 12 11 10 9 15 14 12 9 5 212 1

(15) 1 3 6 0 5 1 8 (16) 0 (17)1 2 4 7 1 6 2 2 5 9 4 0 7 4 1 2 3 5 8 2 7 3 4 8 3 9 6 3 9 3 4 5 6 9 3 8 4 7 2 8 5 2 8 3 6 7 8 9 0 4 9 5 1 7 4 1 7 2 6 A B C D E 5 0 6 6 3 0 6 1 5 8 F G H I J K 1 7 -1 0-2 0-3 0-4 L M N O P Q R 8 2 9 5 0 4 7 9 S T U V W X Y Z

比较难的几道经典题目:

1、把N个同学排成一排, 由前向后按1,2,1,2......报数, 报单数的走出队伍, 报双数的向前

靠拢重新组成一排, 然后再1,2,1,2......报数, 报单数的走出队伍, 问剩下最后一个人时, 这个人原来在哪个位置.(N由键盘输入)

2、N个猴子选大王,他们坐在圆桌周围,座号依次为1??N,从1号开始报数,数到M

的猴子便退出,从下一个人起重新报数,数到M的也退出,不断进行下去直到最后一个猴子,它就是大王了,编程打印大王的座号。(N、M由键盘输入)

3、一只兔子躲进了10个环形分布洞的某一个中,狼在第一个洞中没有找到兔子,就隔一

个洞,到第三个洞去找,也没有找到,就间隔两个洞,到第六个洞去找,以后每次多一个洞去找兔子?这样下去,请问兔子能幸免遇难吗?如果能那应该躲在哪个洞中?

35

从现在开始就完全结束了第一阶段的学习,只要学会了十三章和十四章,并能熟练的接触相关的题目,初中一等奖就像囊中取物了,因此这两章的学习以及练习还有与这两章相关的优化算法显得尤为重要。

第十三章 自定义函数和过程

PASCAL语言提供了大量的标准函数及标准过程供我们直接使用,但有时我们也会用到非标准的函数或过程,尤其是在做递归、回溯、搜索问题时,使用PASCAL语言的自定义函数、过程功能,与BASIC相比,能帮我们节省至少一半以上的时间。同样一个搜索问题,用BASIC语言如果要2个小时编出程序,用PASCAL语言就可能不要1个小时。

第一节、自定义函数 自定义函数也是在程序头部说明,其本身就相当于一个小程序,也有其头部及主体。语法如下:

FUNCTION 函数名(形式参数表):函数值的数据类型; 函数的头部(常/变量说明); BEGIN 函数语句;(其中一定要有一句对函数名的赋值) END; {注意:这里是分号}

以上整个部分都位于程序的头部。自定义函数由“FUNCTION”引导,名称自定,形式参数表是指一个函数要求输入的参数(如:ABS(3.12),括号中的3.12就是形式参数),而每一个函数都是得到具体的值,所以也必须要说明该函数的值(即结果)的数据类型。

函数定义好后,就可在程序中调用,调用时和调用标准函数方法一样,都是把函数作为表达式或表达式中的一部分,放在赋值语句中或直接放在输出语句中。

[例7、1]编一程序,求两个自然数的最大公约数。 Var n,m:integer; Function num(a,b:integer):integer; Var c:integer; Begin If a>b then c:=b else c:=a; C:=c+1; Repeat C:=c-1; Until (a mod c=0) and (b mod c=0); Num:=c; End; Begin Write(?please input 2 numbers:?); Readln(m,n); Writeln(num(m,n)); End. 说明程序主体中的两个变量M,N 定义一个函数NUM,要求输入两个形式参数,值为整数 说明只在函数中用到的变量C 函数主体开始 在函数语句中必不可少的一句:对函数名赋值 函数结束 程序主体开始 在WRITELN语句中调用NUM函数 程序主体结束

36

在上述程序头部,定义了一个名为NUM的函数,所以在程序主体中,我们就可以随时调用它了。但一定要注意:在函数程序语句中一定要对函数名赋值,否则,该函数是无效的。另外:输入的数值的类型一定要和形式参数的类型相同。

两个重要概念:全局变量、局部变量

全局变量是在程序主体的头部说明的变量,是可以在程序的各个部分(包括主体、自定义函数、自定义过程)直接使用的。

局部变量是在程序的自定义函数或自定义过程的程序头部说明的变量,它们只能在所在的函数或过程中使用,不能在程序的其它部分使用。

如上述程序中的变量M,N就是全局变量,而变量C就是局部变量。A,B是形式参数(数值参数),是常量而不是变量。

所以,大家在编写PASCAL程序时一定要注意变量的命名,全局变量与局部变量不要取相同的名称。

递 归

这里我们将再一次讨论PASCAL语言的递归算法设计方法。一般的,用BASIC语言实现递归是非常困难的,而用PASCAL语言的自定义函数或过程来实现就要方便、快捷的多,这就是为什么在信息学竞赛中同学们广泛使用PASCAL语言的原因。

我们已经学习自定义函数、过程的编写以及递归的实现方法,这里再简单重复一下。

递归函数

递归函数是PASCAL语言编程中通向高级算法的必由之路,要掌握递归函数必须要先掌握递归这个概念。

什么是递归呢?我们来看一个例题,在此之前我们先学会什么是数列。数列即一序列数的总称,如:1,2,3,4,5,6,7,8??是自然数数列;2,4,6,8,10,??是自然偶数数列;象这种以某种关系定义的数的序列就叫数列。数列的名称可任取,象上述第一个数列如果名为A,第二个数列名为B,则第一个数列的各个数字的名字就为:A1,A2,A3,A4??或A(1),A(2),A(3)??。数列A的数字关系是:(1)A(N)=A(N-1)+1(N>1);(2)A(1)=1;由此两个关系,我们只要知道该数列中任何一个数的序号,就可推知该数的数值。

那么如果对于数列A,我想知道A(100)是多少该如何推算呢? 由上述关系我们已经知道:

A(100)=A(99)+1,即要知道A(100),我们就必须先知道A(99);而 A(99)=A(98)+1;即要知道A(99)就必须先知道A(98);由此类推 A(98)=A(97)+1; ??????

A(3)=A(2)+1;

A(2)=A(1)+1;而此时就已经不用继续推算下去了,因为A(1)是已知的了。 而实际上,上述推算过程就是递归过程。即要完成某个计算,必须先完成其前的另一个计算,以此类推,直到推到一个已知的值为止。

[例1]有一个数列N,已知:N(1)=1,N(X)=N(X-1)*3-1(X>1),求N(100); 我们已经知道,由递归关系,我们要求N(100),就必须知道N(99)??N(1),而最终N(1)是已知的,所以这个递归关系我们就可以用PASCAL语言很好地表现出来。以下我们用递归函数来完成,请大家注意递归的实现方法,即自己调用自己。 Var n100:integer; 定义程序主体中的变量 Function dg(n:integer):integer; 定义自定义函数DG,形式参数1个,用以记录现在是推Begin 算到了第几个数。 If n=1 then dg:=1 递归出口是当N等于1时,DG的值为1 Else begin

37

Dg:=dg(n-1)*3-1; 如果N不等于1,我们就继续递归,这就是递归关系式 End; End; Begin 程序主体 N100:=dg(100); 调用递归函数 Writeln(n100); End. 由上可以看出,用递归函数来实现算法,程序主体可以变得非常简单,只需少数几句即可。而递归函数就显得至关重要了,由上述程序可以看出,递归函数的实现实际上就是一个自己调用自己的函数。直到调用到已知的数为止。递归问题我们还将在递归过程中详细分析。

由上可见,递归过程实际上只有一句,IF 条件 THEN 出口 ELSE 调用下一次递归;

第二节、自定义过程 我们已经学过很多的标准过程,如:WRITE,READLN,STR等等,这些都是PASCAL的标准过程,我们可以随时调用。但有的时候,我们在程序中的不同地方会用到相同的一些语句,这时,我们就会把这些语句组合成一个自定义过程,以便在不同地方调用,这样,就可以节省大量的时间。并且,利用自定义过程,我们能够非常简单的实现递归、回溯。

自定义过程的说明语法如下(在程序头部说明): procedure 过程名(形式参数表); 过程变量(局部变量)说明部分; begin

语句体;

end; {此处是分号!}

自定义过程的调用语法如下: 过程名(数值参数表);

自定义过程实际上就是一个小的程序,只不过是划分开来,成为一个过程,然后在程序主体中以过程名来调用这些语句。

自定义过程的形式参数与自定义函数的用法一样,是输入过程中要用到的不同的输入值。如果过程中不要用到形式参数值,那么在说明过程的时候,过程名后面就不用加括号来说明形式参数。

[例7、3]编写一个程序,在屏幕上打印以下图形。 $$$$$ $$$$$ $$$$$

$$$$$ $$$$$

分析,我们已经编写过类似的程序,这里我们将用一个过程来打印每一行的五个“$”号。只不过每一行开头的位置不同,所以我们把控制开头位置的数值做为一个形式参数,另外,把每行要把多少个“$”也作为形式参数之一。 Var I:integer; Procedure printrow(n,m:integer); Var r:integer; Begin Write(? ?:n); 形式参数N控制每行前多少个空格,M为每行多少字符 38

For r:=1 to m do begin Write(?$?); End; Writeln; End; Begin For I:=1 to 5 do begin Printrow(I,5); End; 打印每行前N个空格 每行打印M个字符 输入数值参数,每行前I个空格,每行5个字符 End. 上述过程中我们只有两个需输入的参数,有时我们的过程中也会用到输出的参数,如STR(N,S)过程,N是输入的参数,而S是输出的参数,即输入N转化为字符串S输出。这种有输出参数的过程在形式参数说明中有所不同,即输出参数要用VAR来引导。下例就是这种情况。

[例7、4]编写一个程序,求X的N次方。 我们知道,PASCAL语言中没有求乘方的标准函数或过程,这里我们将自己编一个求乘方的过程,而该过程的形式参数就必须有两个输入参数,另外,我们计算出的幂值必须输出到一个变量中,这个变量也必须放在形式参数中,只不过这个参数与输入参数是不同的,所以必须以VAR引导加以说明,程序如下: Var x,n:integer; C:longint; Procedure cm(a,b:integer;var d:longint); Var I:integer; Begin D:=1; For I:=1 to b do begin D:=d*a; End; End; Begin Write(?please input x,n: ?); Readln(x,n); Cm(x,n,c); Writeln(c); End. 请大家一定要看懂得上述程序的形式参数部分,分清其中的输入与输出参数。

递归过程

我们从一个例题中来看看递归的实际实现及运行过程。

[例2]打印‘A’、‘B’、‘C’、‘D’、‘E’这五个字符任意排列的所有情况。

分析,此题可用五重循环来做,但那样就把此题给复杂化了,运行速度也要慢很多,而此题用递归过程来做的话就要简单许多。我们把递归过程定为每次从五个字符中取一个字符,当然这个字符必须与已经取得的字符全不相同,而我们取得的字符存放在一个字符串中,并把它作为形式参数(这一点至关重要,否则答案将完全错误)。当我们已经取完五个字符

39

说明主程序中要用到的X,N变量; 说明乘幂C,用长整数型 过程CM,二个输入函数,D为输出变量 程序主体开始 调用CM过程,输入X,N,输出为C


信息学初级教程(8).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:宁波市紧固件重点企业名录

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: