收藏 分享(赏)

东北师范大学信息学选论第三章一、二节.ppt

上传人:dzzj200808 文档编号:3350771 上传时间:2018-10-17 格式:PPT 页数:130 大小:704KB
下载 相关 举报
东北师范大学信息学选论第三章一、二节.ppt_第1页
第1页 / 共130页
东北师范大学信息学选论第三章一、二节.ppt_第2页
第2页 / 共130页
东北师范大学信息学选论第三章一、二节.ppt_第3页
第3页 / 共130页
东北师范大学信息学选论第三章一、二节.ppt_第4页
第4页 / 共130页
东北师范大学信息学选论第三章一、二节.ppt_第5页
第5页 / 共130页
点击查看更多>>
资源描述

1、第三章 构造法,构造法:就是根据题设条件或结论所具有的特征、性质,构造出满足条件或结论的数学模型,借助于该数学模型解决问题的方法,在现实世界中,有大量事物存在着许多相似或相近的规律,存在着本质相同的东西。正因为如此,在求解非标准题的过程中就有可能形成一些常用的方法思路(策略),按照这些方法思路分析和求解试题,一般可使解题过程变得容易一些。这些方法思路统称为构造法。由于构造法比较综合地反映了选手的智慧、知识基础和创造性思维的能力,因此是联赛的考核重点。,从数学方法的分类来看,构造的数学模型属于初等模型或优化模型。一般地,数学模型具有三大功能: 1解释功能: 利用数学模型说明事物发生的原因。 2判

2、断功能:利用数学模型判断原来的知识和认识的可靠性。 3预见功能:利用数学模型揭示事物的发展规律,为人们的行为提供指导或参考。,构造法解题的思路或步骤可以归纳为:,构造法解题的类型一般有:,1.数学建模:通过沿用经典的数学思想建立起模型;或者提取现实世界中的有效信息,用简明的方式表达其规律,这种规律可以是一条代数公式、一幅几何图形、一个物理原理、一个化学方程式等等。 2.直接构造问题解答:这是构造法运用的一种简单类型。它只能针对问题本身,探索其独有性质,不具备可推广性。无论是直接构造问题解答还是数学建模,都要通过算法来实现。,如何设计一个有较低编程复杂度和时空复杂度且结构清晰的算法,十分重要。通

3、常考虑的因素有: (1)选择的模型必须尽量多地体现问题的本质特征。但这并不意味着模型越复杂越好、冗余的信息会影响算法的效率。 (2)模型的建立不是一个一蹴而就的过程,而是要经过反复地检验、修改,在实践中不断完善。 (3)数学模型通常有严格的格式,但程序编写形式可不拘一格。,构造与建模是一个复杂的抽象过程。我们要善于描视问题的本质,寻找突破口,进而选择适当的模型。构造的模型可以帮助我们认识问题,不同的模型从不同的角度反映问题,可以引发不同的思路,起到发散思维的作用。,但认识问题的最终目的是解决问题,模型的固有性质可帮我们建立算法,其优劣可以通过时空复杂度等指标来衡量,但最终还是以程序的运行结果为

4、标准。所以模型不是一成不变的,同样要通过各种技术不断优化。模型的产生虽然是人脑思维的产物,但它仍然是客观事物在人脑中的反映。所以要培养良好的建模能力,还必须依靠在平时的学习中积累丰富的知识和经验。,对应策略:将问题a对应另一个便于思考或有求解方法的问题b,化繁为简,变未知为已知。对应经典问题 对应简单问题 对应数学问题,在建模过程中经常使用的策略有,分治策略:将问题的规模逐渐减少,可明显降低解决问题的复杂程度。算法设计的这种策略称之为分治策略,即对问题分而治之。 递推的分治策略 递归的分治策略,归纳策略:归纳策略则是通过列举试题本身的特殊情况,经过深入分析,最后概括出事物内在的一般规律,并得到

5、一种高度抽象的解题模型。 递推式 递归式 制定目标 贪心方案,在自然界或日常生活中,许多现象具有不确定的性质,很难建立数据模型,一般采用模拟策略 模拟策略:模拟某个过程,通过改变数学模型的各种参数,进而观察变更这些参数所引起过程状态的变化,由此展开算法设计。模拟题没有固定的模式,一般形式有两种:,随机模拟:题目给定或者隐含某一概率。设计者利用随机函数和取整函数设定某一范围的随机值,将符合概率的随机值作为参数。然后根据这一模拟的数学模型展开算法设计。由于解题过程借助了计算机的伪随机数发生数,其随机的意义要比实际问题中真实的随机变量稍差一些,因此模拟效果有不确定的因素;,过程模拟:题目不给出概率,

6、要求编程者按照题意设计数学模型的各种参数,观察变更这些参数所引起过程状态的变化,由此展开算法设计。模拟效果完全取决于过程模拟的真实性和算法的正确性,不含任何不确定因素。由于过程模拟的结果无二义性,因此竞赛大都采用过程模拟。模拟的解题方法一般有三种类型 直叙式模拟 筛选法模拟 构造法模拟,第一节、对应策略,将问题a对应于另一个便于思考或已有求解方法的问题 b ,化繁为简,变未知为已知。 对应经典问题 对应简单问题 对应数学问题,一一对应技术是一种重要的策略。它的核心是求同,通过举一反三、触类旁通地对已经解决的类似问题和有关事实作联想,推导出事物间的联系,从而全面、深入地认识和分析事物。“世界上没

7、有完全不同的东西”,相似点的普遍存在为我们使用对应策略解题提供了基础。但是对应并不等于等价,两个问题间的表面相似并不等于本质的联系。对应策略不仅要分析问题间的共同点,还要分析问题间的不同点,是一种异中求同的思维方法,一、对应经典问题,经典问题及其算法的知识积累是解题的基础,竞赛的许多试题最终都可以转化为经典问题,因此必须尽可能多地掌握经典问题及其算法的知识。解题时,心中经常回忆已经解决的经典问题和有关解法,往往会收到意想不到的效果。当然这些试题并不直接以经典问题的原貌出现。我们必须合理运用求同思维、求异思维比较两者间的相同点和不同点,通过适当的方法将试题转化为经典问题。,【例1】计算最少的公路

8、造价现有 n 个城市间的交通网,边上的权是公路造价,任一对城市都是可以连通的。现在要用公路把 n 个城市连接起来,这至少需要修筑n-1条公路。如何设计可使得这 n 条公路的总造价最少。 输入:顶点数 n 和边数 e ; 以下有 e 行,每行包括一条边的两个顶点。 输出: n - 1 行,每行为连接一条公路的两个城市序号。,分析:我们以城市为顶点,公路为边,公路的造价为边权,构造一张具有 n 个顶点的带权连通图,这张连通图的生成树有 n - 1 条边。 问题对应为:如何在所有可能的生成树中,寻找各边的权的总和为最小的一棵生成树。显然,这个问题就是经典的最小生成树问题。,下图为 6 个城市间的交通

9、网,边上的权是公路造价。修筑 5 条公路的方案如下:,Prim算法 设G=(V,E)是连通带权图V=0,1,n-1,用邻接矩阵cij表示图G中顶点i和顶点j之间的邻接关系及边的权,若i,j不相连,则cij置为最大值99。构造G的最小生成树的Prim算法的基本思想是:首先置S=0,只要S是V的真子集,就作如下的贪心选择:选取满足条件iS,jV-S,且cij最小的边,将顶点j添加到S中。这个过程一直进行到S=V时为止。过程中选取到的所有边恰好构成G的一棵最小生成树。,带权图,按Prim算法选取边的过程,在上述Prim算法中,还应当考虑如何有效地找出满足条件iS,jV-S,且权cij最小的边(i,j

10、)。实现这个目的的较简单的办法是设置两个数组closest和lowcost。在Prim算法执行过程中,先找出V-S中使lowcost值最小的顶点j,然后根据数组closest选取边(j,closestj),最后将j添加到S中,并对closest和lowcost作必要的修改。用这个办法实现的Prim算法所需的计算时间为W(n2),#include using namespace std; const int MAXINT=1000; const int INF=99; const int N=6; void main() int cNN=99,10,99,99,19,21,10,99, 5, 6

11、,99,11,99, 5,99, 6,99,99,99, 6, 6,99,18,14,19,99,99,18,99,33,21,11,99,14,33,99;Prim(c); ,void Prim(int cNN) int lowcostMAXINT; /存放当前结点相连的权值int closestMAXINT; /存放最近结节bool sMAXINT; s0=true; /放入起始结点for(int i=1;iN;i+) lowcosti=c0i;closesti=0;si=false;for(i=1;iN;i+) int min=INF; int j=0;for(int k=0;kN;k+

12、)if(lowcostkmin) ,Kruskal算法,Kruskal算法构造G的最小生成树的基本思想是,首先将G的n个顶点看成n个孤立的连通分支。将所有的边按权从小到大排序。然后从第一条边开始,依边权递增的顺序查看每一条边,并按下述方法连接2个不同的连通分支:当查看到第k条边(v,w)时,如果端点v和w分别是当前2个不同的连通分支T1和T2中的顶点时,就用边(v,w)将T1和T2连接成一个连通分支,然后继续查看第k+1条边;如果端点v和w在当前的同一个连通分支中,就直接再查看第k+1条边。这个过程一直进行到只剩下一个连通分支时为止。,对前面的连通带权图,按Kruskal算法顺序得到的最小生成

13、树上的边如下图所示。,【 例 2 】挖地雷在一个地图上有n个地窖(n=20),每个地窖中埋有一定数量的地雷,同时,给出地窖之间的联系路径。 当地窖及其连接的数据给出之后,某人可以从任一处开始挖地雷,然后可以沿着连接路径往下挖(仅能选择一条路径),挖的过程中允许某人重复经过地窖。当无连接时,挖地雷工作结束。设计一个挖地雷的方案,使某人能挖到最多的地雷。,输入格式: n (表示地窖的个数) w1,w2,w3,wn a(1,2)a(1,n) a(2,3)a(2,n) a(n-1,n) 表示地窖之间连接路径(其中aij表示地窖 i 和地窖 j 之间是否有通路:如果通,则 aij=1,不通 aij=0)

14、 输出格式: r1-r2 rk (挖地雷的顺序) max (为挖地雷的数量),例如: V1,V2, V3, V6表示地窖。下图给出了一个示例:,分析:我们将地窖设为顶点,地窖之间的通路设为边,每个地窖中的地雷数设为顶点的权,使得问题对应一个顶点带权的无向图,解题的目的是要在这张图中寻找一条路径,该条路径途经的地窖所含的地雷数最多。但是,是否允许某人重复经过地窖是问题的关键。,如果不允许某人重复经过地窖,则最佳路径为 1-2-3 ,挖到的地雷数为 13 ;如果允许某人重复经过地窖,则最佳路径为 1 -2 -3 -2 -4 ,挖到的地雷数为 14 。,不允许重复的求解方法带有明显的阶段特征,允许重

15、复则不具备阶段特征。允许重复与不允许重复对应两种不同的解决方法。 允许某人重复经过地窖实际上是允许挖地雷的顺序中出现回路。无论该人怎样挖,其经过的路径必然在一个连通子图中。我们采用计算无向图传递闭包的方法找出所有的连通子图,并计算出其中顶点权(即地雷数)和最大的一个连通子图。最后,从该连通子图的任一个顶点出发,通过深度优先搜索输出挖地雷的顺序。,【例3】 换车问题,一个城市有 n 个车站,已知 m 条连接这些车站的公共汽车单向路线。求站1至站n的最少换车数。输入: n m 以下 m 行依次列出每条线路的车站序号。输出:最少换车次数。,分析:这个问题对我们来讲并不陌生。如果将问题要求改为“求站

16、1 到站 n 最少经过多少站”,就变为我们相当熟悉的最短路径的典型应用。即令有向图G=,|V|=n,若vi, vj属于E当且仅当i站,j站在某条线路上相邻,(Vi ,Vj)的权Wij设为1。显然,汽车线路经过的站数=路径顶点数=路径边数+1=路径的权和+1。为使总站数最少,只要使路径的权和最小,即只要求出图G中Vi至Vj间的最短路径即可。,但现在的问题是求最少换车次数,虽然它与求经过最少站数总是有共同背景,但要求不同。我们化异为同,重新对原图G作了修正。若 Vi,Vj属于E当且仅当站 i 与站 j 依次在同一条公共汽车线路上(Vi可直达Vj),Wij仍为1。然后运用求最短路径方法计算V1 至V

17、n的最短路径长度,其长度减1即为最少换车次数。,由上可见,对应策略使用得如何,既与其掌握经典算法的多少和理解的透彻程度有关,也与其应用经典算法于实践的能力有关,更与其拓展经典算法应用范围的创造力息息相关。,二、对应简单问题,有些试题的求解方法原本很简单,但由于其表现形式陌生,因此乍看感到棘手。但只要你果断地抓住主要矛盾,舍弃与目标无关的次要信息,去粗取精,去伪存真,由此及彼,由表及里,便可以返朴归真,将试题与一个简单的问题对应起来,【例5】密码锁 (lock),凭借你多年的开锁经验,你马上断定眼前这扇门用的是密码锁。只见锁身上有 n 行数字,在每行数字末尾都有好几个数字拨盘。看着这一行行多少不

18、一的数字和数字末尾留下的空格,你忽然想起了小时候经常玩的一个游戏:找规律。这个游戏就是给你一个数列的前几项,让你填出后一项,例如: 2 4 6 ( 8 ) 1 4 9 ( 16 ),在玩游戏的过程中,你发现了一个窍门,所有这类问题,都可以用这种方法解决:对于一个已知前 m 项的数列 a1 , a2 , a3 , ,am,一定可以找到惟一一个不超过m-1次的多项式f(x),使得 f(1) = a1 , f (2) = a2 f (m)=am ,那么 f(m+1)就是要找的下一项。现在你决定用这种方法试着打开眼前这把密码锁。,输入:第一行是一个整数 n,代表门上共有n行数字,n=100。以下 n

19、行,每行对应门上的一行数字,每行的数字不超过 1000 个。输入的数字之间用空格隔开,每行末尾没有多余的空格。输入的数字都是绝对值小于108的整数。 输出:输出应该包括 n 行,每一行是根据输入数据的规律推出的下一个数字,顺序与输入数据相对应。结果的绝对值都小于 108 。,分析:(1)构造数列的通项公式: 这是最直接的方法。对于已知m项的数列,构造出的通项公式共有m项,当i=m时,有且仅有一项不为零,而且等于 ai .例如数列前 3 项为1,3,5, 通项公式为:,这种方法的缺点是运算过程中数的规模比较大,如果用高精度计算,时空效率可能无法接受。如果不用高精度,恐怕得不到准确解。,(2)求数

20、列的 r 阶差数列 定理:如果一个数列的通项公式是关于自然数 n 的 r 次多项式,那么这个数列是r阶等差数列。这个定理的证明很简单,只要反复进行以g(n)=f(n)-f(n-1)的运算,求数列的差数列,就会发现通项公式的次数每迭带一次都会降低一次,最终原数列的 r 阶差数列就是一个常数列。也就是说原数列是一个 r 阶等差数列。,在这道题里,已知这个数列的通项公式有m-1 项,那么这个数列就是一个m-1阶的等差数列.于是就可以借助等差数列求出数列的第m+1项,例如表所示的数列 1 , 4 , 9方法二比较简捷,要计算的数据不是很大,而且计算量较小。算法的时间复杂度为w(m2/2), m*(m+

21、1)/2 由于计算过程中有许多数据不需要保存,所以空间需求是w(1)。,long r_cal(long num,int m) long result=0; /存放结果for(int j=m-1;j0;j-) /计算m-1阶等差数列的等差值for(int k=0;k=j-1;k+)numk=numk+1-numk;for(j=0;jm;j+)result=result+numj; /计算第j行的最后一项return result; ,【例6】 空中都市,在一个未来的空中都市中,有很多个小岛(城区)。现在要求在这些岛之间架一些桥梁(桥是架在两个岛之间的)。要求:首先,如果A与B之间有桥,B与C之间

22、有桥,则A与C之间就不能再架桥了,即对于城市中的任意三个岛,不能在其中两两都架上桥。在这样的前提下,要求架的桥数最多(不考虑具体的空间结构问题),并计算其中的一个可行方案。,输入文件只包含一行,该行为一个非负整数n( 0=n=1000 ) ,即城市中有n个小岛。 输出文件:桥数的最大值 k,以下为 k 行,每行为一座桥相邻的两个小岛序号(a , b) 输入示例: 6 输出示例: 9 (1,4) (1,5) (1,6) (2,4) (2,5) (2,6) (3,4) (3,5) (3,6),分析:按照题意,如果小岛A与小岛B之间、小岛B与小岛C之间和小岛A 与小岛C 之间都有桥的话,则说明A,

23、B, C三个小岛之间存在传递性。试题要求构造一个含n个顶点且满足下述条件的图: (1)任三个顶点间不含传递性; (2)图中所含边数最多。,我们通过下述方法将空中都市问题对应一个简单问题:把n个小岛分为尽量平均的两部分,第一组为n/2或(n-1)/2个顶点,第二组为n/2 或(n + 1)/2 个顶点。然后第一组的每一个顶点分别向第二组的所有顶点引出,如图所示:,由此得出桥的数目是:,下面,我们来证明这个构造方法的正确性。由于两组的任一对顶点之间都有边相连,因此如果再架桥的话,只能在同组的一对顶点之间进行。如果在某一组的顶点 i 和顶点 j 间架桥,则由于顶点 i 和顶点 j 与另一组的任一个顶

24、点 k 相连,使得顶点 i 、顶点 j 和顶点 k 之间存在传递关系,这是不允许的。而一个数拆分成两个数的积,两个数的值愈接近,积愈大。由此可见,按照上述方法得出的图所含边数最多。,#include using namespace std; int main() int n; /n为岛数cinn;if (n%2=0) coutn*n/4endl;else cout(n-1)*(n+1)/4endl;for(int i=1;i=n/2;i+) /枚举第一组岛屿for(int j=n/2+1;j=n;j+) /枚举第二组岛屿cout(i,j)endl; /输出方案return 0; ,三、对应数学

25、问题运用己学到的数学知识,对试题给出的各个对象及其关系进行分析、演绎、归纳,从而建立一个清晰简练的解析式,使得试题与某个数学问题对应。当然,这个数学问题的计算量非人工演算所能及,必须译成算法语言,通过计算机运算方可完成。对应数学问题的方式有两种: (1) 机理分析法 (2) 统计分析法,1机理分析法根据客观事物的特性,分析其内部的机理,弄清关系,在适当抽象的条件下,得到可以描述事物属性的数学工具。我们在联赛中可以用这种方法建立数学模型,然后根据所对应的算法求出解。通过抽象建模得出对应信息原型的数学模型;然后将数学模型理论对应到算法,并编程实现;最后通过算法的执行得到问题的解。,【例7】国际象棋

26、( knight ),国际象棋是我们休息娱乐时常玩的游戏。在各个棋子中,马的行进方式最为特殊,也为人们所津津乐道。我们都知道:马走的是“日”字,也就是说每次都是向水平或竖直方向移动1格,而向另一个方向移动2格,所以也可称作是 1x2 的马(走法如图所示)。在图中我们看到一个马有 8 种跳的方向。,小明是一个数学爱好者,他将马的走法重新定义了一下,重新定义后的广义马成为 nxm 的马。为了研究广义马,小明让马从(0 , 0 )出发,随意地在一张足够大的棋盘上移动。他发现,有时候广义马总是无法跳入某些格子中,比如 2x2 的马永远不可能跳到(1, 1),这令他非常感兴趣。他希望知道对于给定的 n

27、, m , nx m的广义马是否能够跳到所有的格子。由于 n , m 可以非常大,这令小明花了许多功夫在尝试上,但仍不能得出肯定的结论。于是他就来找你这个计算机专家帮忙了。,输入:在输入文件knight.in 中包含了多组测试数据,每组测试数据占一行。每组测试数据由 2 个数 n , m (1 = n =108 , 1 =m =108)组成,表示广义马的类型。文件最后一行由2个0 表示文件结束。 输出:将答案输出到文件 knight.out 中,每组测试数据占一行。如果马能跳到指定的位置输出 YES ,否则输出 Impossible 。 分析:通常,马的遍历问题都是用搜索解决的。但本题中有一些

28、特殊的地方:棋盘是无穷大的,马也是广义的。另外,更重要的是问题规模相当大(1=n =108 , 1 =m =108) ,所以需要深入地研究这个问题。由于计算哪些类型的马可以遍历整个棋盘似乎有些困难,于是我们就先来研究对于给定的广义马,存在哪些到不了的特殊位置。,首先从最简单的 1Xn 的广义马开始分析: (1)当 n 为奇数时,将棋盘染成黑白相间。若(0 , 0)为白色,因为每跳一步,马在竖直和水平方向前进的步数之和(1+n)为偶数。所以自(0 , 0)出发的马始终在白格子上跳跃,黑色的格子是马永远到不了的。,(2)当 n 为偶数时,我们有这样的移动方案(如图 ( b )所示),使得马从(0

29、, 0)开始经过一系列的跳步后,到(1 , 0 )的位置,也就是说可以让马到达相邻的格子,所以马可以遍历整个棋盘。,下面我们分析一般的广义马。我们能否将 nxm 的广义马对应 1xn 的广义马呢?分析三种情况: 第 1 种情况:若n,m 有最大公约数 p ( p 1 ) ,则马只能跳到形似(pxs , pxt)的格子上,其他的格子都到不了。 第 2 种情况:若 n+m 是偶数,类似于 1xn 马的情况,马只能在同色的格子内跳动,不能遍历棋盘。,第3种情况:若 n +m 为奇数,且 n , m 互质。不妨设 n 为奇数,那么 m 为偶数。因为 1xn 马的问题已经被彻底解决,所以很自然的想将 n

30、xm 经过一系列变换转化成 1xn 马的问题。我们可以看到马的跳法本质上是 4 种(另 4 种可以看成是以下 4 种跳法反跳一步) : ( m , n ) ( m ,-n) ( n , m ) ( n ,-m) 马经过跳 p 次 ,q 次 ,r次 ,s次 后 水平方向的位移为(p+q ) m +(r+s) n 竖直方向的位移为(p-q)n + (r-s) m 为了利用 1xn 马的结论,解不定方程(p+q) m + (r+s)n=1 因为n, m 互质。该方程一定有解(p0, q0, r0, s0).,因为m 是偶数, n 是奇数,所以( r0 + s0)是奇数。因为马要遍历整个棋盘,其竖直和

31、水平方向前进的步数之和(p0+q0)m+(r0+s0)n+(p0-q0)n+(r0-s0)m 为奇数, 所以( p0-q0)是偶数。(p0-q0 ) n + ( r0-s0) m是偶数。 也就是马通过一系列的跳动所得到的效果相当于 1xlen 的马跳一步的效果( len =(p0-q0 ) n + ( r0-s0 ) m)。根据前面的结论, 1 xlen 的马可以遍历整个棋盘,所以当 n+m 为奇数且 n , m 互质时, nxm 的马可以遍历整个棋盘。 算法的时间复杂度为W( 1 ) ,空间需求为W( 1 )。,#include long gcd(long a,long b) /计算n和m的

32、最大公约数 if (b=0) return a;else return gcd(b,a%b); void main() long n,m; /n,m为广义马的类型cinnm; /若n+m为偶数,无解if (n+m)%2=0) coutm long temp; temp=n; m=n; n=temp; /若n,m互质,输出成功,否则失败if (gcd(n,m)=1) cout“YES“; else cout“Impossible“; ,1657【例8】棋盘上的距离,国际象棋的棋盘是黑白相间的8 * 8的方格,棋子放在格子中间。如下图所示:,1 2 3 4 5 6 7 8,h g f e d c

33、b a,王、后、车、象的走子规则如下: 王:横、直、斜都可以走,但每步限走一格。 后:横、直、斜都可以走,每步格数不受限制。 车:横、竖均可以走,不能斜走,格数不限。 象:只能斜走,格数不限。写一个程序,给定起始位置和目标位置,计算王、后、车、象从起始位置走到目标位置所需的最少步数,Input第一行是测试数据的组数t(0 = t = 20)。以下每行是一组测试数据,每组包括棋盘上的两个位置,第一个是起始位置,第二个是目标位置。位置用“字母-数字“的形式表示,字母从“a“到“h“,数字从“1“到“8“。 Output 对输入的每组测试数据,输出王、后、车、象所需的最少步数。如果无法到达,就输出“

34、Inf“. Sample Input 2 a1 c3 f5 f8 Sample Output 2 1 2 1 3 1 1 Inf,解题思路,首先,王、后、车、象彼此独立,应分别考虑。 我们假设起始位置与终止位置在水平方向上的距离是x,在竖直方向上的距离是y 王:所需要最小步数是min(x,y)+abs(x-y) 后:1步:当x=y或x=0或y=0 2步:当x!y 车:1步:当x=0或y=0 2步:x!=0且y!=0 象:只能斜走,因此横纵坐标增减的数值相等,所以横纵坐标之间的奇偶性无论如何都保持不变。横纵坐标之差为奇数的点和为偶数的点不能相互到达。当它们属于同一类点时,1步,当xy时2步,当x

35、!y时,#include #include using namespace std; int main() int n,i; cinn; /n是测试数据组数for(i=0;ibeginend;int x=abs(begin0-end0); int y=abs(begin1-end1);if (x=0 ,2统计分析法,我们在一时得不到事物的特征机理的情况下,可通过某种方法测试得到一些数据(即问题的部分解),再利用数理统计知识对数据进行处理,从而得到最终的数学模型。统计分析法是相对于机理分析法的逆向思维。这种方法在实验性学科中应用十分广泛。例如在研究f(x)= sinx 的图像时,我们先取一些特殊

36、点,再根据其大致走向作出函数图像。在联赛中,我们亦可以用手工或简单的程序求出问题的部分解,然后分析出其中的规律,得到数学模型。,先从信息原型出发,通过手工或简单的程序得到问题的部分解。然后通过对部分解的分析,运用数理统计得到信息原型的主要属性(这里的属性大部分是某些规律),从而建立数学模型,然后通过算法得出问题的全部解。,【 例9 】 极值问题,m , n 为整数,且满足下列两个条件: m ,n属于 1,2,3, , k (1=k=109 ); (n2-mn-m2)2=1. 由键盘输入 k ,求一组满足上述两个条件的 m , n 并且使 m2+ n2 的值最大。 分析:本题是一道数学性很强的试

37、题。信息原型本身就具有很强的抽象性。如果一开始就在抽象中分析,是很难理清思路的。面对(n2-mn-m2)2=1这本来就十分抽象的关系式,由于缺乏继续抽象的线索,自然也就无法通过机理分析法得到对应的数学模型。这时统计分析法就有了用武之地,首先,通过手工测试,我们得出了如表所示的一些小的数据结果: 当m=1时, 可求出n=2; 当m=2时, 可求出n=3; 当m=3时, 可求出n=5; 当m=4时, n无整数解; 当m=5时, 可求出n=8; 我们将整理出的m,n排列在一起,有1 2 3 5 8,令人惊奇的是: n , m 随着 k 的增长以斐波纳契数列形式增长!我们于是猜测:问题的解就是小于等于

38、 k 的最大的相临两个斐波纳契数。有了问题的研究方向,我们就朝这个方向去设法证明自己的猜想。,如果我们的猜想正确,那么当(m,n)是方程(n2-mn-m2)2=1的一组解时,根据斐波纳契数列关系, ( n,n+m)也一定是方程的一组解。即(n+m)2-(n+m)n-n2)2=1 则:(n2+2mn+m2-n2-mn-n2)2=1(mn+m2 -n2)2=1若(n2-mn-m2)2=1 成立,则:以上各步可逆,所以当(n,m)是方程的一组解时,(n,n+m)一定是方程的另一组解。,#include using namespace std; int main() /m,n,next是斐波纳契数列的

39、头三项long m=1,n=1,next=2,k=0;/读入一个范围中的Kwhile(k1000000000) cink;while(next=k) /找出m,n的最大值 m=n;n=next;next=m+n; coutm n; return 0; ,【例10】取石子问题,有两堆石子,数量可能不同。有两个人轮流取。每次有两种不同的取法。一是在任意一堆中取走任意多的石子;二是在两堆中同时取走相同数量的石子。最后把石子全部取完的是胜者。现在给出初始的两堆石子的数目,如果轮到你来取,又假设双方都采取最好的策略,问最后你是胜者还是败者。,输入文件只有一行,包含两个非负整数 a 和 b ,表示两堆石子

40、的数目。(a=109 ,b=109 )。 输出文件也只有一行,包含一个数字。如果最后你是胜者,则输出 1 。反之,则输出0。 输入示例: 6 10 输出示例: 0,分析:我们无法直接从两堆石子的取法中找到规律。在这种情况下,只能在测试得到的部分解答中寻找出路。(1)分析失败的情况 测试结果有两种可能 : 失败的情况: ( 1 , 2 ) ( 3 , 5 ) ( 4 , 7 ) ( 6 , 10 ) ( 8 , 13 ) ( 9 , 15 ) ( 11 , 18 ) ( 12 , 20 ) ( 14 , 23 ) ( 16 , 26 ) ( 17 , 28 ) ( 19 , 31 ) ( 21

41、, 34 ) 胜利的情况: ( 1, 1 ) ( 1 , 3 ) ( 1 , 4 ) 。胜利的情况比失败的情况多得多。,在上述两种情况,我们选择相对容易得出的失败情况展开分析,寻找规律。 从 1 开始的每一个数字,在这些数字对中都会出现一次且仅会出现一次; 数对的差成等差数列 1 , 2 , 3 , 4 有些数对的数字排列(例如( 1 , 2 ) ( 3 , 5 ) ( 8 , 13 ) )来自斐波纳契数列(例如 1 , 2 , 3 , 5 , 8 , 13 , 21 ) ; 有些数对(例如( 4 , 7 )和( 11 , 18 ) ),虽然不是标准斐波纳契数列中的数字,但还是符合斐波纳契数列

42、的规则的;, 如果数对(a,b)出现在其中,则(a+b,a+2b)也必然出现在数对中(相反的结论是不对的) ; 数对中两个数之比都非常接近于0.618 ,即著名的黄金分割数。 (2)判别 a , b 的输赢由于从 1 开始的每一个自然数,按照斐波纳契数列的规则不重复地出现在失败的数对中,因此,可以得出如下结论:,若数对按照递增顺序排列成( a , b ),且满足则确定 ( a , b )失败。由此得出算法:,#include Void main() long x,y,temp;cinxy;/按照递增顺序排列 x 和 y if (xy) temp=x;x=y;y=temp;/若 x 和 y 接近

43、黄金分割数,则失败;否则胜利if (x=y/1.618)cout0;elsecout1; ,本节作业,简要回答如下问题: 1.什么是构造法?设计构造法模型通常要考虑哪些因素? 2.在构造法建模过程中经常使用的策略有哪些? 3.对应策略通常分为哪几种类型? 4.对应数学问题有几种方式,其基本思想分别是什么?,写出算法思想,例1 例5 例6 例8 例9,第二节、分治策略,将问题的规模逐渐减少,可明显降低解决问题的复杂程度。算法设计的这种策略称之为分治策略,即对问题分而治之。用分治策略求解一个问题,所需的时间是由子问题的个数、大小以及把这个问题分解为子问题所需的工作总量来确定。一般来说,把任意大小的

44、问题尽可能地等分成两个子问题较为有效。竞赛中常用的分治策略有: ( 1 )递推的分治策略 ( 2 )递归的分治策略,一、分治算法总体思想,将要求解的较大规模的问题分割成k个更小规模的子问题。,对这k个子问题分别求解。如果子问题的规模仍然不够小,则再划分为k个子问题,如此递归的进行下去,直到问题规模足够小,很容易求出其解为止。将求出的小规模的问题的解合并为一个更大规模的问题的解,自底向上逐步求出原来问题的解。,因此:分治法的设计思想是,将一个难以直接解决的大问题,分割成一些规模较小的相同问题,以便各个击破,分而治之。当n=2时,分治法又称为二分法。 分治算法在每一层递归或递推分为三个步骤: 分:

45、将原问题分解成一系列的子问题; 治:递归或递推地解各子问题,若子问题足够小,则直接解之; 合:将子问题的结果合并成原问题的解。 可以看到,决定算法时间效率的关键在于合并过程。,二、递归的概念,直接或间接地调用自身的算法称为递归算法。用函数自身给出定义的函数称为递归函数。由分治法产生的子问题往往是原问题的较小模式,这就为使用递归技术提供了方便。在这种情况下,反复应用分治手段,可以使子问题与原问题类型一致而其规模却不断缩小,最终使子问题缩小到很容易直接求出其解。这自然导致递归过程的产生。分治与递归像一对孪生兄弟,经常同时应用在算法设计之中,并由此产生许多高效算法。下面来看几个实例。,例1 阶乘函数

46、,阶乘函数可递归地定义为:边界条件与递归方程是递归函数的二个要素,递归函数只有具备了这两个要素,才能在有限次计算后得出结果。,边界条件,递归方程,例2 Fibonacci数列,无穷数列1,1,2,3,5,8,13,21,34,55,称为Fibonacci数列。,递归方程,边界条件,第n个Fibonacci数可递归地计算如下:int fibonacci(int n)if (n = 1) return 1;return fibonacci(n-1)+fibonacci(n-2);,例3 Ackerman函数,当一个函数及它的一个变量是由函数自身定义时,称这个函数是双递归函数。,前2例中的函数都可以

47、找到相应的非递归方式定义:本例中的Ackerman函数却无法找到非递归的定义,A(n,m)的自变量m的每一个值都定义了一个单变量函数: m=0时,A(n,0)=n+2 m=1时,A(n,1)=A(A(n-1,1),0)=A(n-1,1)+2,和A(1,1)=2故A(n,1)=2*n m=2时,A(n,2)=A(A(n-1,2),1)=2A(n-1,2),和A(1,2)=A(A(0,2),1)=A(1,1)=2,故A(n,2)= 2n 。 m=3时,类似的可以推出m=4时,A(n,4)的增长速度非常快,以至于没有适当的数学式子来表示这一函数。,例4 排列问题,设计一个递归算法生成n个元素r1,r

48、2,rn的全排列。 设R=r1,r2,rn是要进行排列的n个元素, Ri=R-ri。perm(x),集合x中元素的全排列。(ri)perm(x)表示在全排列perm(x)的每一个排列前加上前缀得到的排列。R的全排列可归纳定义如下: 当n=1时,perm(R)=(r),其中r是集合R中唯一的元素; 当n1时,perm(R)由(r1)perm(R1), (r2)perm(R2),(rn)perm(Rn)构成。,template void perm(Type list,int k,int m) /产生listk:m的所有排列if (k=m) /单元素排列for(int i=0;i=m;i+) coutlisti;coutendl;else /多元素序列,递归产生排列for(int i=k;i=m;i+) swap(listk,listi);perm(list,k+1,m);swap(listk,listi); ,#include #include using namespace std; int main() /示例0到4的全排列。int a5=0,1,2,3,4;perm(a,0,4);/示例a到d的全排列char b5=“abcd“;perm(b,0,3);return 0; ,

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 高等教育 > 大学课件

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报