信息学奥赛——算法入门教程497.pdf
《信息学奥赛——算法入门教程497.pdf》由会员分享,可在线阅读,更多相关《信息学奥赛——算法入门教程497.pdf(35页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、全国青少年信息学奥林匹克联赛 算法讲义 算法基础篇.2 算法具有五个特征:.2 信息学奥赛中的基本算法(枚举法).4 采用枚举算法解题的基本思路:.4 枚举算法应用.4 信息学奥赛中的基本算法(回溯法).7 回溯基本思想.8 信息学奥赛中的基本算法(递归算法).10 递归算法的定义:.10 递归算法应用.11 算法在信息学奥赛中的应用(递推法).14 递推法应用.14 算法在信息学奥赛中的应用(分治法).18 分治法应用.18 信息学奥赛中的基本算法(贪心法).21 贪心法应用.21 算法在信息学奥赛中的应用(搜索法一).24 搜索算法应用.25 算法在信息学奥赛中的应用(搜索法二).28 广
2、度优先算法应用.29 算法在信息学奥赛中的应用(动态规划法).32 动态规划算法应用.33 算法基础篇 学习过程序设计的人对算法这个词并不陌生,从广义上讲,算法是指为解决一个问题而采用的方法和步骤;从程序计设的角度上讲,算法是指利用程序设计语言的各种语句,为解决特定的问题而构成的各种逻辑组合。我们在编写程序的过程就是在实施某种算法,因此程序设计的实质就是用计算机语言构造解决问题的算法。算法是程序设计的灵魂,一个好的程序必须有一个好的算法,一个没有有效算法的程序就像一个没有灵魂的躯体。算法具有五个特征:1、有穷性:一个算法应包括有限的运算步骤,执行了有穷的操作后将终止运算,不能是个死循环;2、确
3、切性:算法的每一步骤必须有确切的定义,读者理解时不会产生二义性。并且,在任何条件下,算法只有唯一的一条执行路径,对于相同的输入只能得出相同的输出。如在算法中不允许有“计算 8/0”或“将 7 或 8 与 x 相加”之类的运算,因为前者的计算结果是什么不清楚,而后者对于两种可能的运算应做哪一种也不知道。3、输入:一个算法有 0 个或多个输入,以描述运算对象的初始情况,所谓0个输入是指算法本身定义了初始条件。如在5 个数中找出最小的数,则有 5 个输入。4、输出:一个算法有一个或多个输出,以反映对输入数据加工后的结果,这是算法设计的目的。它们是同输入有着某种特定关系的量。如上述在 5 个数中找出最
4、小的数,它的出输出为最小的数。如果一个程序没有输出,这个程序就毫无意义了;5、可行性:算法中每一步运算应该是可行的。算法原则上能够精确地运行,而且人能用笔和纸做有限次运算后即可完成。如何来评价一个算法的好坏呢?主要是从两个方面:一是看算法运行所占用的时间;我们用时间复杂度来衡量,例如:在以下 3个程序中,(1)x:=x+1(2)for i:=1 to n do x:=x+1(3)for i:=1 to n do for j:=1 to n do x:=x+1 含基本操作“x 增 1”的语句 x:=x+1 的出现的次数分别为 1,n 和 n2则这三个程序段的时间复杂度分别为 O(1),O(n),
5、O(n2),分别称为常量阶、线性阶和平方阶。在算法时间复杂度的表示中,还有可能出现的有:对数阶 O(log n),指数阶 O(2n)等。在 n 很大时,不同数量级的时间复杂度有:O(1)O(log n)O(n)O(nlog n)O(n2)O(n3)O(2n),很显然,指数阶的算法不是一个好的算法。二是看算法运行时所占用的空间,既空间复杂度。由于当今计算机硬件技术发展很快,程序所能支配的自由空间一般比较充分,所以空间复杂度就不如时间复杂度那么重要了,有许多问题人们主要是研究其算法的时间复杂度,而很少讨论它的空间耗费。时间复杂性和空间复杂性在一定条件下是可以相互转化的。在中学生信息学奥赛中,对程序
6、的运行时间作出了严格的限制,如果运行时间超出了限定就会判错,因此在设计算法时首先要考虑的是时间因素,必要时可以以牺牲空间来换取时间,动态规划法就是一种以牺牲空间换取时间的有效算法。对于空间因素,视题目的要求而定,一般可以不作太多的考虑。我们通过一个简单的数值计算问题,来比较两个不同算法的效率(在这里只比较时间复杂度)。例:求 N!所产生的数后面有多少个0(中间的 0 不计)。算法一:从 1 乘到 n,每乘一个数判断一次,若后面有 0 则去掉后面的 0,并记下0 的个数。为了不超出数的表示范围,去掉与生成 0 无关的数,只保留有效位数,当乘完 n 次后就得到 0 的个数。(pascal 程序如下
7、)var i,t,n,sum:longint;begin t:=0;sum:=1;readln(n);for i:=1 to n do begin sum:=sum*i;while sum mod 10=0 do begin sum:=sum div 10;inc(t);计数器增加 1 end;sum:=sum mod 1000;舍去与生成 0 无关的数 end;writeln(t:6);end.算法二:此题中生成 O 的个数只与含 5 的个数有关,n!的分解数中含 5 的个数就等于末尾 O 的个数,因此问题转化为直接求 n!的分解数中含 5 的个数。var t,n:integer;begin
8、 readln(n);t:=0;repeat n:=n div 5;inc(t,n);计数器增加 n until n5;writeln(t:6);end.分析对比两种算法就不难看出,它们的时间复杂度分别为 O(N)、O(logN),算法二的执行时间远远小于算法一的执行时间。在信息学奥赛中,其主要任务就是设计一个有效的算法,去求解所给出的问题。如果仅仅学会一种程序设计语言,而没学过算法的选手在比赛中是不会取得好的成绩的,选手水平的高低在于能否设计出好的算法。下面,我们根据全国分区联赛大纲的要求,一起来探讨信息学奥赛中的基本算法。信息学奥赛中的基本算法(枚举法)枚举法,常常称之为穷举法,是指从可能
9、的集合中一一枚举各个元素,用题目给定的约束条件判定哪些是无用的,哪些是有用的。能使命题成立者,即为问题的解。采用枚举算法解题的基本思路:(1)确定枚举对象、枚举范围和判定条件;(2)一一枚举可能的解,验证是否是问题的解 下面我们就从枚举算法的的优化、枚举对象的选择以及判定条件的确定,这三个方面来探讨如何用枚举法解题。枚举算法应用 例 1:百钱买百鸡问题:有一个人有一百块钱,打算买一百只鸡。到市场一看,大鸡三块钱一只,小鸡一块钱三只,不大不小的鸡两块钱一只。现在,请你编一程序,帮他计划一下,怎么样买法,才能刚好用一百块钱买一百只鸡?算法分析:此题很显然是用枚举法,我们以三种鸡的个数为枚举对象(分
10、别设为 x,y,z),以三种鸡的总数(x+y+z)和买鸡用去的钱的总数(x*3+y*2+z)为判定条件,穷举各种鸡的个数。下面是解这个百鸡问题的程序 var x,y,z:integer;begin for x:=0 to 100 do for y:=0 to 100 do for z:=0 to 100 do 枚举所有可能的解 if(x+y+z=100)and(x*3+y*2+z div 3=100)and(z mod 3=0)then writeln(x=,x,y=,y,z=,z);验证可能的解,并输出符合题目要求的解 end.上面的条件还有优化的空间,三种鸡的和是固定的,我们只要枚举二种鸡
11、(x,y),第三种鸡就可以根据约束条件求得(z=100-x-y),这样就缩小了枚举范围,请看下面的程序:var x,y,z:integer;begin for x:=0 to 100 do for y:=0 to 100-x do begin z:=100-x-y;if(x*3+y*2+z div 3=100)and(z mod 3=0)then writeln(x=,x,y=,y,z=,z);end;end.未经优化的程序循环了 1013 次,时间复杂度为 O(n3);优化后的程序只循环了(102*101/2)次,时间复杂度为 O(n2)。从上面的对比可以看出,对于枚举算法,加强约束条件,缩
12、小枚举的范围,是程序优化的主要考虑方向。在枚举算法中,枚举对象的选择也是非常重要的,它直接影响着算法的时间复杂度,选择适当的枚举对象可以获得更高的效率。如下例:例 2、将 1,2.9 共 9 个数分成三组,分别组成三个三位数,且使这三个三位数构成 1:2:3 的比例,试求出所有满足条件的三个三位数.例如:三个三位数 192,384,576 满足以上条件.(NOIP1998pj)算法分析:这是 1998 年全国分区联赛普及组试题(简称 NOIP1998pj,以下同)。此题数据规模不大,可以进行枚举,如果我们不加思地以每一个数位为枚举对象,一位一位地去枚举:for a:=1 to 9 do for
13、 b:=1 to 9 do for i:=1 to 9 do 这样下去,枚举次数就有 9次,如果我们分别设三个数为 x,2x,3x,以 x 为枚举对象,穷举的范围就减少为,在细节上再进一步优化,枚举范围就更少了。程序如下:var t,x:integer;s,st:string;c:char;begin for x:=123 to 321 do枚举所有可能的解 begin t:=0;str(x,st);把整数 x 转化为字符串,存放在 st 中 str(x*2,s);st:=st+s;str(x*3,s);st:=st+s;for c:=1 to 9 do枚举 9 个字符,判断是否都在 st 中
14、 if pos(c,st)0 then inc(t)else break;如果不在 st 中,则退出循环 if t=9 then writeln(x,x*2,x*3);end;end.在枚举法解题中,判定条件的确定也是很重要的,如果约束条件不对或者不全面,就穷举不出正确的结果,我们再看看下面的例子。例 一元三次方程求解(noip2001tg)问题描述 有形如:ax3+bx2+cx+d=0 这样的一个一元三次方程。给出该方程中各项的系数(a,b,c,d 均为实数),并约定该方程存在三个不同实根(根的范围在-100 至 100 之间),且根与根之差的绝对值=1。要求由小到大依次在同一行输出这三个实
15、根(根与根之间留有空格),并精确到小数点后 2 位。提示:记方程 f(x)=0,若存在 2 个数 x1 和 x2,且 x1x2,f(x1)*(x2)0,则在(x1,x2)之间一定有一个根。样例 输入:1 -5 -4 20 输出:-2.00 2.00 5.00 算法分析:由题目的提示很符合二分法求解的原理,所以此题可以用二分法。用二分法解题相对于枚举法来说很要复杂很多。此题是否能用枚举法求解呢?再分析一下题目,根的范围在-100 到 100 之间,结果只要保留两位小数,我们不妨将根的值域扩大 100 倍(-10000=x=10000),再以根为枚举对象,枚举范围是-10000到 10000,用原
16、方程式进行一一验证,找出方程的解。有的同学在比赛中是这样做 var k:integer;a,b,c,d,x:real;begin read(a,b,c,d);for k:=-10000 to 10000 do begin x:=k/100;if a*x*x*x+b*x*x+c*x+d=0 then write(x:0:2,);end;end.用这种方法,很快就可以把程序编出来,再将样例数据代入测试也是对的,等成绩下来才发现这题没有全对,只得了一半的分。这种解法为什么是错的呢?错在哪里?前面的分析好象也没错啊,难道这题不能用枚举法做吗?看到这里大家可能有点迷惑了。在上面的解法中,枚举范围和枚举对
17、象都没有错,而是在验证枚举结果时,判定条件用错了。因为要保留二位小数,所以求出来的解不一定是方程的精确根,再代入 ax3+bx2+cx+d 中,所得的结果也就不一定等于 0,因此用原方程ax3+bx2+cx+d=0 作为判断条件是不准确的。我们换一个角度来思考问题,设 f(x)=ax3+bx2+cx+d,若 x 为方程的根,则根据提示可知,必有 f(x-0.005)*(x+0.005)0,如果我们以此为枚举判定条件,问题就逆刃而解。另外,如果 f(x-0.005)=0,哪么就说明 x-0.005 是方程的根,这时根据四舍 5 入,方程的根也为 x。所以我们用(f(x-0.005)*f(x+0.
18、005)0)和(f(x-0.005)=0)作为判定条件。为了程序设计的方便,我们设计一个函数 f(x)计算 ax3+bx2+cx+d 的值,程序如下:$N+var k:integer;a,b,c,d,x:extended;function f(x:extended):extended;计算 ax3+bx2+cx+d 的值 begin f:=(a*x+b)*x+c)*x+d;end;begin read(a,b,c,d);for k:=-10000 to 10000 do begin x:=k/100;if(f(x-0.005)*f(x+0.005)a2ar;(2)其中第 i 位数(1=ir-i
19、;我们按以上原则先确定第一个数,再逐位生成所有的 r 个数,如果当前数符合要求,则添加下一个数;否则返回到上一个数,改变上一个数的值再判断是否符合要求,如果符合要求,则继续添加下一个数,否则返回到上一个数,改变上一个数的值按此规则不断循环搜索,直到找出 r 个数的组合,这种求解方法就是回溯法。如果按以上方法生成了第i 位数 ai,下一步的的处理为:(1)若 air-i 且 i=r,则输出这 r 个数并改变 ai 的值:ai=ai-1;(2)若 air-i 且 ir,则继续生成下一位 ai+1=ai-1;(3)若 air-1 则重复:若 air-i,若 i=r,则输出解,并且 ai:=ai-1;
20、若 ir,则继续生成下一位:ai+1:=ai-1;i:=i+1;若 air-i then 符合条件 if i=r then 输出 begin for j:=1 to r do write(aj:3);writeln;ai:=ai-1;end else 继续搜索 begin ai+1:=ai-1;i:=i+1;end else回溯 begin i:=i-1;ai:=ai-1;end;until a1=r-1;end.下面我们再通过另一个例子看看回溯在信息学奥赛中的应用。例 2 数的划分(noip2001tg)问题描述 整数 n 分成 k 份,且每份不能为空,任意两份不能相同(不考虑顺序)。例如:
21、n=7,k=3,下面三种分法被认为是相同的。1,1,5;1,5,1;5,1,1;问有多少种不同的分法。输入:n,k (6n=200,2=k=6)输出:一个整数,即不同的分法。样例 输入:7 3 输出:4 四种分法为:1,1,5;1,2,4;1,3,3;2,2,3;算法分析:此题可以用回溯法求解,设自然数 n 拆分为 a1,a2,ak,必须满足以下两个条件:(1)n=a1+a2+ak ;(2)a1=a2=ak (避免重复计算);现 假 设 己 求 得 的 拆 分 数 为 a1,a2,ai,且 都 满 足 以 上 两 个 条 件,设sum=n-a1-a2-ai,我们根据不同的情形进行处理:(1)如
22、果 i=k,则得到一个解,则计数器 t 加 1,并回溯到上一步,改变 ai-1的值;(2)如果 i=ai,则添加下一个元素ai+1;(3)如果 ik 且 sumai,则说明达不到目标,回溯到上一步,改变ai-1的值;算法实现步骤如下:第一步:输入自然数n,k 并初始化;t:=0;i:=1;ai:=1;sum:=n-1;nk:=n div k;第二步:如果 a1=ai则继续搜索;若 sum=ai then 判断是否回溯 begin inc(i);ai:=ai-1;sum:=sum-ai;end继续搜 else begin dec(i);inc(ai);sum:=sum+ai+1-1;end;回溯
23、 end;until a1nk;writeln(t);end.回溯法是通过尝试和纠正错误来寻找答案,是一种通用解题法,在 NOIP 中有许多涉及搜索问题的题目都可以用回溯法来求解。信息学奥赛中的基本算法(递归算法)递归算法的定义:如果一个对象的描述中包含它本身,我们就称这个对象是递归的,这种用递归来描述的算法称为递归算法。我们先来看看大家熟知的一个的故事:从前有座山,山上有座庙,庙里有个老和尚在给小和尚讲故事,他说从前有座山,山上有座庙,庙里有个老和尚在给小和尚讲故事,他说 上面的故事本身是递归的,用递归算法描述:procedure bonze-tell-story;begin if 讲话被打
24、断 then 故事结束 else begin 从前有座山,山上有座庙,庙里有个老和尚在给小和尚讲故事;bonze-tell-story;end end;从上面的递归事例不难看出,递归算法存在的两个必要条件:(1)必须有递归的终止条件;(2)过程的描述中包含它本身;在设计递归算法中,如何将一个问题转化为递归的问题,是初学者面临的难题,下面我们通过分析汉诺塔问题,看看如何用递归算法来求解问题;递归算法应用 例 1:汉诺塔问题,如下图,有 A、B、C 三根柱子。A 柱子上按从小到大的顺序堆放了 N 个盘子,现在要把全部盘子从 A 柱移动到 C 柱,移动过程中可以借助 B柱。移动时有如下要求:(1)一
25、次只能移动一个盘子;(2)不允许把大盘放在小盘上边;(3)盘子只能放在三根柱子上;算法分析:当盘子比较多的时,问题比较复杂,所以我们先分析简单的情况:如果只有一个盘子,只需一步,直接把它从 A 柱移动到 C 柱;如果是二个盘子,共需要移动 3 步:(1)把 A 柱上的小盘子移动到 B 柱;(2)把 A 柱上的大盘子移动到 C 柱;(3)把 B 柱上的大盘子移动到 C 柱;如果 N 比较大时,需要很多步才能完成,我们先考虑是否能把复杂的移动过程转化为简单的移动过程,如果要把 A 柱上最大的盘子移动到 C 柱上去,必须先把上面的 N-1 个盘子从 A 柱移动到 B 柱上暂存,按这种思路,就可以把
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 信息学 算法 入门教程 497
限制150内