认证主体:宁夏凯米世纪网络科技有限公司
IP属地:宁夏
统一社会信用代码/组织机构代码
91640100MA774ECW4K
1、全国青少年信息学奥林匹克联赛算法讲义算法基础篇1算法具有五个特征:2信息学奥赛中的基本算法(枚举法)4采用枚举算法解题的基本思路:4枚举算法应用4信息学奥赛中的基本算法(回溯法)7回溯基本思想7信息学奥赛中的基本算法(递归算法)10递归算法的定义:10递归算法应用10算法在信息学奥赛中的应用(递推法)13递推法应用14算法在信息学奥赛中的应用(分治法)17分治法应用18信息学奥赛中的基本算法(贪心法)20贪心法应用21算法在信息学奥赛中的应用(搜索法一)24搜索算法应用24算法在信息学奥赛中的应用(搜索法二)28广度优先算法应用29算法在信息学奥赛中的应用(动态规划法)32动态规划算法应用
2、33算法基础篇学习过程序设计的人对算法这个词并不陌生,从广义上讲,算法是指为解决一个问题而采用的方法和步骤;从程序计设的角度上讲,算法是指利用程序设计语言的各种语句,为解决特定的问题而构成的各种逻辑组合。我们在编写程序的过程就是在实施某种算法,因此程序设计的实质就是用计算机语言构造解决问题的算法。算法是程序设计的灵魂,一个好的程序必须有一个好的算法,一个没有有效算法的程序就像一个没有灵魂的躯体。算法具有五个特征:1、有穷性:一个算法应包括有限的运算步骤,执行了有穷的操作后将终止运算,不能是个死循环;2、确切性:算法的每一步骤必须有确切的定义,读者理解时不会产生二义性。并且,在任何条件下,算
3、法只有唯一的一条执行路径,对于相同的输入只能得出相同的输出。如在算法中不允许有“计算8/0”或“将7或8与x相加”之类的运算,因为前者的计算结果是什么不清楚,而后者对于两种可能的运算应做哪一种也不知道。3、输入:一个算法有0个或多个输入,以描述运算对象的初始情况,所谓0个输入是指算法本身定义了初始条件。如在5个数中找出最小的数,则有5个输入。4、输出:一个算法有一个或多个输出,以反映对输入数据加工后的结果,这是算法设计的目的。它们是同输入有着某种特定关系的量。如上述在5个数中找出最小的数,它的出输出为最小的数。如果一个程序没有输出,这个程序就毫无意义了;5、
7、=0;sum:=1;readln(n);fori:=1tondobeginsum:=sum*i;whilesummod10=0dobeginsum:=sumdiv10;inc(t);计数器增加1end;sum:=summod1000;舍去与生成0无关的数end;writeln(t:6);end.算法二:此题中生成o的个数只与含5的个数有关,n!的分解数中含5的个数就等于末尾o的个数,因此问题转化为直接求n!的分解数中含5的个数。vart,n:integer;beginreadln(n);t:=0;repeatn:=ndiv
9、用的,哪些是有用的。能使命题成立者,即为问题的解。采用枚举算法解题的基本思路:(1)确定枚举对象、枚举范围和判定条件;(2)一一枚举可能的解,验证是否是问题的解下面我们就从枚举算法的的优化、枚举对象的选择以及判定条件的确定,这三个方面来探讨如何用枚举法解题。枚举算法应用例1:百钱买百鸡问题:有一个人有一百块钱,打算买一百只鸡。到市场一看,大鸡三块钱一只,小鸡一块钱三只,不大不小的鸡两块钱一只。现在,请你编一程序,帮他计划一下,怎么样买法,才能刚好用一百块钱买一百只鸡?算法分析:此题很显然是用枚举法,我们以三种鸡的个数为枚举对象(分别设为x,y,z),以三种鸡的总数(x+y+z)和买鸡
10、用去的钱的总数(x*3+y*2+z)为判定条件,穷举各种鸡的个数。下面是解这个百鸡问题的程序varx,y,z:integer;beginforx:=0to100dofory:=0to100doforz:=0to100do枚举所有可能的解if(x+y+z=100)and(x*3+y*2+zdiv3=100)and(zmod3=0)thenwriteln(x=,x,y=,y,z=,z);验证可能的解,并输出符合题目要求的解end.上面的条件还有优化的空间,三种鸡的和是固定的,我们只要枚举二种鸡(x,y),第三种鸡就可以根据约束条件求得(z=100-x-
13、次数就有9次,如果我们分别设三个数为x,2x,3x,以x为枚举对象,穷举的范围就减少为,在细节上再进一步优化,枚举范围就更少了。程序如下:vart,x:integer;s,st:string;c:char;beginforx:=123to321do枚举所有可能的解begint:=0;str(x,st);把整数x转化为字符串,存放在st中str(x*2,s);st:=st+s;str(x*3,s);st:=st+s;forc:=1to9do枚举9个字符,判断是否都在st中ifpos(c,st)0theninc(t)elsebreak;
14、如果不在st中,则退出循环ift=9thenwriteln(x,,x*2,,x*3);end;end.在枚举法解题中,判定条件的确定也是很重要的,如果约束条件不对或者不全面,就穷举不出正确的结果,我们再看看下面的例子。例一元三次方程求解(noip2001tg)问题描述有形如:ax3+bx2+cx+d=0这样的一个一元三次方程。给出该方程中各项的系数(a,b,c,d均为实数),并约定该方程存在三个不同实根(根的范围在-100至100之间),且根与根之差的绝对值=1。要求由小到大依次在同一行输出这三个实根(根与根之间留有空格),并精确到小数点后2位。提示:记方程f(x
15、)=0,若存在2个数x1和x2,且x1x2,f(x1)*(x2)0,则在(x1,x2)之间一定有一个根。样例输入:1-5-420输出:-2.002.005.00算法分析:由题目的提示很符合二分法求解的原理,所以此题可以用二分法。用二分法解题相对于枚举法来说很要复杂很多。此题是否能用枚举法求解呢?再分析一下题目,根的范围在-100到100之间,结果只要保留两位小数,我们不妨将根的值域扩大100倍(-10000=x=10000),再以根为枚举对象,枚举范围是-10000到10000,用原方程式进行一一验证,找出方程的解。有的同学在比赛中是这样做vark:integer;a,b
16、,c,d,x:real;beginread(a,b,c,d);fork:=-10000to10000dobeginx:=k/100;ifa*x*x*x+b*x*x+c*x+d=0thenwrite(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.005)0)和(f(x-0.005)=0)作为判定条件。为了程序设计的方便,我们设计
18、一个函数f(x)计算ax3+bx2+cx+d的值,程序如下:$n+vark:integer;a,b,c,d,x:extended;functionf(x:extended):extended;计算ax3+bx2+cx+d的值beginf:=(a*x+b)*x+c)*x+d;end;beginread(a,b,c,d);fork:=-10000to10000dobeginx:=k/100;if(f(x-0.005)*f(x+0.005)a2ar;(2)其中第i位数(1=ir-i;我们按以上原则先确定第一个数,再逐位生成所有的r个数,如果当前数符合要求,则
19、添加下一个数;否则返回到上一个数,改变上一个数的值再判断是否符合要求,如果符合要求,则继续添加下一个数,否则返回到上一个数,改变上一个数的值按此规则不断循环搜索,直到找出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;若ir,则继续生成下一位:ai+1:=ai-1;i:=i+1;若ai
20、r-ithen符合条件ifi=rthen输出beginforj:=1tordowrite(aj:3);writeln;ai:=ai-1;endelse继续搜索beginai+1:=ai-1;i:=i+1;endelse回溯begini:=i-1;ai:=ai-1;end;untila1=r-1;end.下面我们再通过另一个例子看看回溯在信息学奥赛中的应用。例2数的划分(noip2001tg)问题描述整数n分成k份,且每份不能为空,任意两份不能相同(不考虑顺序)。例如:n=7,k=3,下面三种分法被认为是相同的。1,1,5;1,5,1;5,1,1;问
21、有多少种不同的分法。输入:n,k(6n=200,2=k=6)输出:一个整数,即不同的分法。样例输入:73输出: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)如果i=k,则得到一个解,则计数器t加1,并回溯到上一步,改变ai-1的值;(2)如果i=ai,则添加下
22、一个元素ai+1;(3)如果ik且sumai,则说明达不到目标,回溯到上一步,改变ai-1的值;算法实现步骤如下:第一步:输入自然数n,k并初始化;t:=0;i:=1;ai:=1;sum:=n-1;nk:=ndivk;第二步:如果a1=ai则继续搜索;若sum=aithen判断是否回溯begininc(i);ai:=ai-1;sum:=sum-ai;end继续搜elsebegindec(i);inc(ai);sum:=sum+ai+1-1;end;回溯end;untila1nk;writeln(t);end.回溯法是通过尝试和纠正错误来寻
23、找答案,是一种通用解题法,在noip中有许多涉及搜索问题的题目都可以用回溯法来求解。信息学奥赛中的基本算法(递归算法)递归算法的定义:如果一个对象的描述中包含它本身,我们就称这个对象是递归的,这种用递归来描述的算法称为递归算法。我们先来看看大家熟知的一个的故事:从前有座山,山上有座庙,庙里有个老和尚在给小和尚讲故事,他说从前有座山,山上有座庙,庙里有个老和尚在给小和尚讲故事,他说上面的故事本身是递归的,用递归算法描述:procedurebonze-tell-story;beginif讲话被打断then故事结束elsebegin从前有座山,山上有座庙,庙里有个老和尚在给小和尚讲故
24、事;bonze-tell-story;endend;从上面的递归事例不难看出,递归算法存在的两个必要条件:(1)必须有递归的终止条件;(2)过程的描述中包含它本身;在设计递归算法中,如何将一个问题转化为递归的问题,是初学者面临的难题,下面我们通过分析汉诺塔问题,看看如何用递归算法来求解问题;递归算法应用例1:汉诺塔问题,如下图,有a、b、c三根柱子。a柱子上按从小到大的顺序堆放了n个盘子,现在要把全部盘子从a柱移动到c柱,移动过程中可以借助b柱。移动时有如下要求:(1)一次只能移动一个盘子;(2)不允许把大盘放在小盘上边;(3)盘子只能放在三根柱子上;算法分析
25、:当盘子比较多的时,问题比较复杂,所以我们先分析简单的情况:如果只有一个盘子,只需一步,直接把它从a柱移动到c柱;如果是二个盘子,共需要移动3步:(1)把a柱上的小盘子移动到b柱;(2)把a柱上的大盘子移动到c柱;(3)把b柱上的大盘子移动到c柱;如果n比较大时,需要很多步才能完成,我们先考虑是否能把复杂的移动过程转化为简单的移动过程,如果要把a柱上最大的盘子移动到c柱上去,必须先把上面的n-1个盘子从a柱移动到b柱上暂存,按这种思路,就可以把n个盘子的移动过程分作3大步:(1)把a柱上面的n-1个盘子移动到
26、b柱;(2)把a柱上剩下的一个盘子移动到c柱;(3)把b柱上面的n-1个盘子移动到c柱;其中n-1个盘子的移动过程又可按同样的方法分为三大步,这样就把移动过程转化为一个递归的过程,直到最后只剩下一个盘子,按照移动一个盘子的方法移动,递归结束。递归过程:procedurehanoi(n,a,b,c:integer;);以b柱为中转柱将n个盘子从a柱移动到c柱beginifn=1thenwrite(a,-,c)把盘子直接从a移动到celsebeginhanoi(n-1,a,c,b);以c柱为中转柱将n-1个盘子从a柱移动到b
27、柱write(a,-,c);把剩下的一个盘子从a移动到chanoi(n-1,b,a,c);以a柱为中转柱将n-1个盘子从b柱移动到c柱end;end;从上面的例子我们可以看出,在使用递归算法时,首先弄清楚简单情况下的解法,然后弄清楚如何把复杂情况归纳为更简单的情况。在信息学奥赛中有的问题的结构或所处理的数据本身是递归定义的,这样的问题非常适合用递归算法来求解,对于这类问题,我们把它分解为具有相同性质的若干个子问题,如果子问题解决了,原问题也就解决了。例2求先序排列(noip2001pj)问题描述给出一棵二叉树的中序与后序排列。求出它的先序排列。(约定树结点用不
28、同的大写字母表示,长度8)。样例输入:badcbdca输出:abcd算法分析:我们先看看三种遍历的定义:先序遍历是先访问根结点,再遍历左子树,最后遍历右子树;中序遍历是先遍历左子树,再访问根结点,最后遍历右子树;后序遍历是先遍历左子树,再遍历右子树,最后访问根结点;从遍历的定义可知,后序排列的最后一个字符即为这棵树的根节点;在中序排列中,根结点前面的为其左子树,根结点后面的为其右子树;我们可以由后序排列求得根结点,再由根结点在中序排列的位置确定左子树和右子树,把左子树和右子树各看作一个单独的树。这样,就把一棵树分解为具有相同性质的二棵子树,一直递归下去,当分解的子树为空时,递归结束,在
29、递归过程中,按先序遍历的规则输出求得的各个根结点,输出的结果即为原问题的解。源程序programnoip2001_3;varz,h:string;proceduremake(z,h:string);z为中序排列,h为后序排列vars,m:integer;beginm:=length(h);m为树的长度write(hm);输出根节点s:=pos(hm,z);求根节点在中序排列中的位置ifs1thenmake(copy(z,1,s-1),copy(h,1,s-1);处理左子树ifmsthenmake(copy(z,s+1,m-s),copy(h,s,m-
30、s);处理右子树end;beginreadln(z);readln(h);make(z,h);end.递归算法不仅仅是用于求解递归描述的问题,在其它很多问题中也可以用到递归思想,如回溯法、分治法、动态规划法等算法中都可以使用递归思想来实现,从而使编写的程序更加简洁。比如上期回溯法所讲的例2数的划分问题,若用递归来求解,程序非常短小且效率很高,源程序如下varn,k:integer;tol:longint;proceduremake(sum,t,d:integer);vari:integer;beginifd=ktheninc(tol)elsefori:=tto
31、sumdiv2domake(sum-i,i,d+1);end;beginreadln(n,k);tol:=0;make(n,1,1);writeln(tol);end.有些问题本身是递归定义的,但它并不适合用递归算法来求解,如斐波那契(fibonacci)数列,它的递归定义为:f(n)=1(n=1,2)f(n)=f(n-2)+f(n-1)(n2)用递归过程描述为:funtionfb(n:integer):integer;beginifn3thenfb:=1elsefb:=fb(n-1)+fb(n-2);end;上面的递归过程,调用一次产生二个新的调用,递归次数
33、题本身已经给定,或是通过对问题的分析与化简后确定。可用递推算法求解的题目一般有以下二个特点:(1)问题可以划分成多个状态;(2)除初始状态外,其它各个状态都可以用固定的递推关系式来表示。在我们实际解题中,题目不会直接给出递推关系式,而是需要通过分析各种状态,找出递推关系式。递推法应用例1骑士游历:(noip1997tg)设有一个n*m的棋盘(2=n=50,2=m(2,3)-(4,4)若不存在路径,则输出no任务2:当n,m给出之后,同时给出马起始的位置和终点的位置,试找出从起点到终点的所有路径的数目。例如:(n=10,m=10),(1,5)(起点),(3,5)(终点)输出:2
34、(即由(1,5)到(3,5)共有2条路径)输入格式:n,m,x1,y1,x2,y2(分别表示n,m,起点坐标,终点坐标)输出格式:路径数目(若不存在从起点到终点的路径,输出0)算法分析:为了研究的方便,我们先将棋盘的横坐标规定为i,纵坐标规定为j,对于一个nm的棋盘,i的值从1到n,j的值从1到m。棋盘上的任意点都可以用坐标(i,j)表示。对于马的移动方法,我们用k来表示四种移动方向(1,2,3,4);而每种移动方法用偏移值来表示,并将这些偏移值分别保存在数组dx和dy中,如下表kdxkdyk12122-131241-2根据马走的规则,马可以由(
35、i-dxk,j-dyk)走到(i,j)。只要马能从(1,1)走到(i-dxk,j-dyk),就一定能走到(i,j),马走的坐标必须保证在棋盘上。我们以(n,m)为起点向左递推,当递推到(i-dxk,j-dyk)的位置是(1,1)时,就找到了一条从(1,1)到(n,m)的路径。我们用一个二维数组a表示棋盘,对于任务一,使用倒推法,从终点(n,m)往左递推,设初始值an,m为(-1,-1),如果从(i,j)一步能走到(n,m),就将(n,m)存放在ai,j中。如下表,a3,2和a2,3的值是(4,4),表示从这两个点都可以到达坐标(4,4)。从(1,1)可到达(2,3)、(3,2
36、)两个点,所以a1,1存放两个点中的任意一个即可。递推结束以后,如果a1,1值为(0,0)说明不存在路径,否则a1,1值就是马走下一步的坐标,以此递推输出路径。-1,-14,44,42,3任务一的源程序:constdx:array1.4ofinteger=(2,2,1,1);dy:array1.4ofinteger=(1,-1,2,-2);typemap=recordx,y:integer;end;vari,j,n,m,k:integer;a:array0.50,0.50ofmap;beginread(n,m);fillchar(a,sizeof(a),0);an,m.x:
37、=-1;an,m.y:=-1;标记为终点fori:=ndownto2do倒推forj:=1tomdoifai,j.x0thenfork:=1to4dobeginai-dxk,j-dyk.x:=i;ai-dxk,j-dyk.y:=j;end;ifa1,1.x=0thenwriteln(no)elsebegin存在路径i:=1;j:=1;write(,i,j,);whileai,j.x-1dobegink:=i;i:=ai,j.x;j:=ak,j.y;write(-(,i,j,);end;end;end.对于任务二,也可以使用递推法,用数
38、组ai,j存放从起点(x1,y1)到(i,j)的路径总数,按同样的方法从左向右递推,一直递推到(x2,y2),ax2,y2即为所求的解。源程序(略)在上面的例题中,递推过程中的某个状态只与前面的一个状态有关,递推关系并不复杂,如果在递推中的某个状态与前面的所有状态都有关,就不容易找出递推关系式,这就需要我们对实际问题进行分析与归纳,从中找到突破口,总结出递推关系式。我们可以按以下四个步骤去分析:(1)细心的观察;(2)丰富的联想;(3)不断地尝试;(4)总结出递推关系式。下面我们再看一个复杂点的例子。例2、栈(noip2003pj)题目大意:求n个数通过栈后的排列总数。(1n18)
39、如输入3输出5算法分析:先模拟入栈、出栈操作,看看能否找出规律,我们用f(n)表示n个数通过栈操作后的排列总数,当n很小时,很容易模拟出f(1)=1;f(2)=2;f(3)=5,通过观察,看不出它们之间的递推关系,我们再分析n=4的情况,假设入栈前的排列为“4321”,按第一个数“4”在出栈后的位置进行分情况讨论:(1)若“4”最先输出,刚好与n=3相同,总数为f(3);(2)若“4”第二个输出,则在“4”的前只能是“1”,“23”在“4”的后面,这时可以分别看作是n=1和n=2时的二种情况,排列数分别为f(1)和f(2),所以此时的总数为f(1)*
40、f(2);(3)若“4”第三个输出,则“4”的前面二个数为“12”,后面一个数为“3”,组成的排列总数为f(2)*f(1);(4)若“4”第四个输出,与情况(1)相同,总数为f(3);所以有:f(4)=f(3)+f(1)*f(2)+f(2)*f(1)+f(3);若设0个数通过栈后的排列总数为:f(0)=1;上式可变为:f(4)=f(0)*f(3)+f(1)*f(2)+f(2)*f(1)+f(3)*f(0);再进一步推导,不难推出递推式:f(n)=f(0)*f(n-1)+f(1)*f(n-2)+f(n-1)*f(0);即f(n)=f(i)*f(n-i-1)0i
41、n-1(n=1)var初始值:f(0)=1;有了以上递推式,就很容易用递推法写出程序。a:array0.18oflongint;n,i,j:integer;beginreadln(n);fillchar(a,sizeof(a),0);a0:=1;fori:=1tondoforj:=0toi-1doai:=ai+aj*ai-j-1;writeln(an);end.递推算法最主要的优点是算法结构简单,程序易于实现,难点是从问题的分析中找出解决问题的递推关系式。对于以上两个例子,如果在比赛中找不出递推关系式,也可以用回溯法求解。算法在信息学奥赛中的应用(分治法)分治算法
42、的基本思想是将一个规模为n的问题分解为k个规模较小的子问题,这些子问题相互独立且与原问题性质相同。求出子问题的解,就可得到原问题的解。分治法解题的一般步骤:(1)分解,将要解决的问题划分成若干规模较小的同类问题;(2)求解,当子问题划分得足够小时,用较简单的方法解决;(3)合并,按原问题的要求,将子问题的解逐层合并构成原问题的解。分治法应用例1、比赛安排(noip1996)设有2n(n=6)个球队进行单循环比赛,计划在2n-1天内完成,每个队每天进行一场比赛。设计一个比赛的安排,使在2n-1天内每个队都与不同的对手比赛。例如n=2时的比赛安排为:队1234比赛
43、1-23-4第一天1-32-4第二天1-42-3第三天算法分析:此题很难直接给出结果,我们先将问题进行分解,设m=2n,将规模减半,如果n=3(即m=8),8个球队的比赛,减半后变成4个球队的比赛(m=4),4个球队的比赛的安排方式还不是很明显,再减半到两个球队的比赛(m=2),两个球队的比赛安排方式很简单,只要让两个球队直接进行一场比赛即可:1221分析两个球队的比赛的情况不难发现,这是一个对称的方阵,我们把这个方阵分成4部分(即左上,右上,左下,右下),右上部分可由左上部分加1(即加m/2)得到,而右上与左下部分、左上与右下部分别相等。因此我们也可以把
44、这个方阵看作是由m=1的方阵所成生的,同理可得m=4的方阵:1234214334124321同理可由m=4方阵生成m=8的方阵:1234567821436587341278564321876556781234658721437856341287654321这样就构成了整个比赛的安排表。在算法设计中,用数组a记录2n个球队的循环比赛表,整个循环比赛表从最初的1*1方阵按上述规则生成2*2的方阵,再生成4*4的方阵,直到生成出整个循环比赛表为止。变量h表示当前方阵的大小,也就是要生成的下一个方阵的一半。源程序:vari,j,h,m,n:integer;a:
45、array1.32,1.32ofinteger;beginreadln(n);m:=1;a1,1:=1;h:=1;fori:=1tondom:=m*2;repeatfori:=1tohdoforj:=1tohdobeginai,j+h:=ai,j+h;构造右上角方阵ai+h,j:=ai,j+h;构造左下角方阵ai+h,j+h:=ai,j;构造右下角方阵end;h:=h*2;untilh=m;fori:=1tomdobeginforj:=1tomdowrite(ai,j:4);writeln;end;end.在分治算法中,若将原问
47、二分法求解此题。由题意知(i,i+1)中若有根,则只有一个根,我们枚举根的值域中的每一个整数x(-100x100),设定搜索区间x1,x2,其中x1=x,x2=x+1。若:f(x1)=0,则确定x1为f(x)的根;f(x1)*f(x2)0,则确定根x不在区间x1,x2内,设定x2,x2+1为下一个搜索区间;若确定根x在区间x1,x2内,采用二分法,将区间x1,x2分成左右两个子区间:左子区间x1,x和右子区间x,x2(其中x=(x1+x2)/2)。如果f(x1)*f(x)0,则确定根在左区间x1,x内,将x设为该区间的右界值(x2=x),继续对左区间进行
48、对分;否则确定根在右区间x,x2内,将x设为该区间的左界值(x1=x),继续对右区间进行对分;上述对分过程一直进行到区间的间距满足精度要求为止(即x2-x10.005)。此时确定x1为f(x)的根。源程序:$n+varx:integer;a,b,c,d,x1,x2,xx:extended;functionf(x:extended):extended;beginf:=(a*x+b)*x+c)*x+d;end;beginread(a,b,c,d);forx:=-100to100dobeginx1:=x;x2:=x+1;iff(x1)=0thenwrite(x1:0:2,)elseiff(x1)*f(x2)=0.005dobeginxx:=(x1+x2)/2;iff(x1)*f(x