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

加入VIP,免费下载
 

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

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

下载须知

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

版权提示 | 免责声明

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

分冶策略生成PDF.docx

1、分冶策略生成PDF分治策略(Divide and Conquer)一、算法思想任何一个可以用计算机求解的问题所需的计算时间都与其规模有关。问题规模越小,解题所需的计算时间往往也越少,从而也越容易计算。想解决一个较大的问题,有时是相当困难的。分治法的思想就是,将一个难以直接解决的大问题,分割成一些规模较小的相同问题,以便各个击破,分而治之。分而治之方法与软件设计的模块化方法非常相似。为了解决一个大的问题,可以: 1) 把它分成两个或多个更小的问题; 2) 分别解决每个小问题; 3) 把各小问题的解答组合起来,即可得到原问题的解答。小问题通常与原问题相似,可以递归地使用分而治之策略来解决。1、解决

2、算法实现的同时,需要估算算法实现所需时间。分治算法时间是这样确定的: 解决子问题所需的工作总量(由子问题的个数、解决每个子问题的工作量决定)合并所有子问题所需的工作量。2、分治法是把任意大小问题尽可能地等分成两个子问题的递归算法3、分治的具体过程: begin 开始 if 问题不可分 then 返回问题解 else begin 从原问题中划出含一半运算对象的子问题1; 递归调用分治法过程,求出解1; 从原问题中划出含另一半运算对象的子问题2; 递归调用分治法过程,求出解2; 将解1、解2组合成整修问题的解; end; end; 结束 二、分治策略的应用(1)找出伪币 给你一个装有1 6个硬币的

3、袋子。1 6个硬币中有一个是伪造的,并且那个伪造的硬币比真的硬币要轻一些。你的任务是找出这个伪造的硬币。问题简析为了帮助你完成这一任务,将提供一台可用来比较两组硬币重量的仪器,利用这台仪器,可以知道两组硬币的重量是否相同。比较硬币1与硬币2的重量。假如硬币1比硬币2轻,则硬币1是伪造的;假如硬币2比硬币1轻,则硬币2是伪造的。这样就完成了任务。假如两硬币重量相等,则比较硬币3和硬币4。同样,假如有一个硬币轻一些,则寻找伪币的任务完成。假如两硬币重量相等,则继续比较硬币5和硬币6。按照这种方式,可以最多通过8次比较来判断伪币的存在并找出这一伪币。另外一种方法就是利用分而治之方法。假如把1 6硬币

4、的例子看成一个大的问题。第一步,把这一问题分成两个小问题。随机选择8个硬币作为第一组称为A组,剩下的8个硬币作为第二组称为B组。这样,就把1 6个硬币的问题分成两个8硬币的问题来解决。第二步,判断A和B组中是否有伪币。可以利用仪器来比较A组硬币和B组硬币的重量。假如两组硬币重量相等,则可以判断伪币不存在。假如两组硬币重量不相等,则存在伪币,并且可以判断它位于较轻的那一组硬币中。最后,在第三步中,用第二步的结果得出原先1 6个硬币问题的答案。若仅仅判断硬币是否存在,则第三步非常简单。无论A组还是B组中有伪币,都可以推断这1 6个硬币中存在伪币。因此,仅仅通过一次重量的比较,就可以判断伪币是否存在

5、。现在假设需要识别出这一伪币。把两个或三个硬币的情况作为不可再分的小问题。注意如果只有一个硬币,那么不能判断出它是否就是伪币。在一个小问题中,通过将一个硬币分别与其他两个硬币比较,最多比较两次就可以找到伪币。这样,1 6硬币的问题就被分为两个8硬币(A组和B组)的问题。通过比较这两组硬币的重量,可以判断伪币是否存在。如果没有伪币,则算法终止。否则,继续划分这两组硬币来寻找伪币。假设B是轻的那一组,因此再把它分成两组,每组有4个硬币。称其中一组为B1,另一组为B2。比较这两组,肯定有一组轻一些。如果B1轻,则伪币在B1中,再将B1又分成两组,每组有两个硬币,称其中一组为B1a,另一组为B1b。比

6、较这两组,可以得到一个较轻的组。由于这个组只有两个硬币,因此不必再细分。比较组中两个硬币的重量,可以立即知道哪一个硬币轻一些。较轻的硬币就是所要找的伪币。(2)二分搜索(折半查找)算法思想:将数列按有序化(递增或递减)排列,查找过程中采用跳跃式方式查找,即先以有序数列的中点位置为比较对象,如果要找的元素值小于该中点元素,则将待查序列缩小为左半部分,否则为右半部分。通过一次比较,将查找区间缩小一半。折半查找是一种高效的查找方法。它可以明显减少比较次数,提高查找效率。但是,折半查找的先决条件是查找表中的数据元素必须有序。算法步骤描述:step1 首先确定整个查找区间的中间位置:mid = ( le

7、ft + right )/ 2step2 用待查关键字值与中间位置的关键字值进行比较; 若相等,则查找成功 若大于,则在后(右)半个区域继续进行折半查找 若小于,则在前(左)半个区域继续进行折半查找 Step3 对确定的缩小区域再按折半公式,重复上述步骤。最后,得到结果:要么查找成功, 要么查找失败。折半查找的存储结构采用一维数组存放。折半查找算法举例 对给定数列(有序) 3,5,11,17,21,23,28,30,32,50,按折半查找算法,查找关键字值为30的数据元素。折半查找的算法讨论:优点: ASL(平均查找长度)log2n,即每经过一次比较,查找范围就缩小一半。经log2n 次计较就

8、可以完成查找过程。缺点:因要求有序,所以要求查找数列必须有序,而对所有数据元素按大小排序是非常费时的操作。例如:由于数据按升序排列,故用折半查找最快捷。program binsearch;const max=10;var num:array1.max of integer;i,n:integer;procedure search(x,a,b:integer);var mid:integer;beginif a=b thenif x=numa then writeln(Found:,a) else writeln(Number not found)else beginmid:=(a+b) div

9、 2;if xnummid then search(x,mid,b);if xnummid then search(x,a,mid);if x=nummid then writeln(Found:,mid);end;end;beginwrite(Please input 10 numbers in order:);for i:=1 to max do read(num);write(Please input the number to search:);readln(n);search(n,1,max);end.非递归算法:PROCEDURE BINASEARCH( A,N,K ); BEGI

10、N S:=1; T:=N; I:=0; WHILE S=T DO BEGIN M:=(S+T) DIV 2; IF AMK THEN IF AMK THEN T:=M-1 ELSE S:=M+1 ELSE BEGIN I:=M; S:=T+1; END END; IF I0 THEN WRITELN(I,AI) ELSE WRITELN(NO FOUND!) END;(3)循环赛日程表有n个编号为1到n的运动员参加某项运动的单循环比赛,即每个运动员要和所有其他运动员进行一次比赛。试为这n个运动员安排一个比赛日程,使得每个运动员每天只进行一场比赛,且整个比赛在n-1天内结束。输入运动员人数n(n

11、0时,A1,J表示第1名运动员在第J天的比赛对手。【分析提示】由于N个运动员要进行单循环比赛,且在N-1天内要结束全部比赛,经过分析,当且仅当N为2的整次幂时,问题才有解,当然解是不惟一的。这样可以将运动员分成两组:1,2,N/2和N/2+1,N/2+2,N。给第一组运动员安排一个比赛日程,得到一个N/2阶的方阵A1;同时给第二组的运动员安排一个比赛日程,同样会得到一个N/2阶的一个方阵A2。考虑到比赛的性质,设定第1个运动员在某一天的比赛对手为第K个运动员,则第K个运动员在同一天的比赛对手必然是第1个运动员,即若有A1,J=K,则A1,K=I。因此原问题的解(一个N阶方阵)可以由分解后的两个

12、子问题的解,按下图所示形式合并起来。同时每一个子问题又可以按照上述的二分法分解下去,直至每个组中仅有2个运动员时为止。procedure arrangment (K, N: integer); begin if n=2 then 处理只有2名运动员的情况,递归终止条件 begin A K, 0: =K; A K, 1: =K+I; A K+I, 0: =K+I; A K+I, 1: =K; end else begin arrangment (K, N div 2); arrangment (K + N div 2, N div 2); 递归分解原问题与求解子问题 for I: =K to K

13、 + (N div 2) -1 do 合并子问题, 构造原问题的解 AI,J for J: = (N div 2) to N-1 do A I, J:=A I+(N div 2), J-(N div 2); for I:=K+(N div 2) to K+N-1 do for J:= (N div 2) to N-1 do A I, j:=A I-(N div 2), J-(N div 2);end; end;(4)在n个元素中找出最大元素和最小元素我们可以把这n个元素放在一个数组中,用直接比较法求出。算法如下:BEGIN MIN:=A1:MAX:=A1; FOR I:=2 TO N DO B

14、EGIN IF AI MAX THEN MAX:=AI; IF AI MIN THEN MIN:=AI;END 上面这个算法需比较2(N-1)次,即时间复杂度是2(N-1)。能否找到更好的算法呢?我们用分治策略来讨论。 我们把n个元素分成 A1=A1,.,Aint(n/2) 和 A2=AINT(N/2)+1,.,AN两组,分别求这两组的最大值和最小值,然后分别将这两组的最大值和最小值相比较,求出全部元素的最大值和最小值。 如果A1和A2中的元素多于两个,则再用上述方法各分为两个子集。直至子集中元素至多两个元素为止。 例如有下面一组元素: -13,13,9,-5,7,23,0,15。用分治策略比

15、较的过程如下: 图中每个方框中,左边是最小值,右边是最大值。从图中看出,用这种方法一共比较了10次,比直接比较法的14次减少4次,即约减少了1/3。procedure maxmin(i,j,max,min);BEGIN CASE J-I OF 0:MAX:=AI;MIN:=AI; 1:IF AI =N,符合此条件的最小那个X)。 其时间复杂度为:O(nlogn).所需辅助存储空间为:O(n)。参考程序:a为序列表,tmp为辅助数组 procedure merge(var a:listtype; p,q,r:integer); 将已排序好的子序列ap.q与aq+1.r合并为有序的tmpp.r v

16、ar I,j,t:integer; tmp:listtype; begin t:=p;i:=p;j:=q+1;t为tmp指针,I,j分别为左右子序列的指针 while (t=r) do begin if (ir) or (ai=aj) 满足取左边序列当前元素的要求 then begin tmpt:=ai; inc(i); end else begin tmpt:=aj;inc(j); end; inc(t); end; for i:=p to r do ai:=tmpi; end;merge procedure merge_sort(var a:listtype; p,r: integer);

17、 合并排序ap.r var q:integer; begin if pr then begin q:=(p+r-1) div 2; merge_sort (a,p,q); merge_sort (a,q+1,r); merge (a,p,q,r); end; end; main begin merge_sort(a,1,n); end.(6)快速排序【基本思想】快速排序对冒泡排序的一种改进。它的基本思想是:通过一躺排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成

18、有序序列。【算法过程】设要排序的数组是A1AN,首先任意选取一个数据(通常选用第一个数据)作为关键数据,然后将所有比它小的数都放到它前面,所有比它大的数都放到它后面,这个过程称为一躺快速排序。一躺快速排序的算法是: 1)、设置两个变量I、J,排序开始的时候I:=1,J:=N; 2)以第一个数组元素作为关键数据,赋值给X,即X:=A1; 3)、从J开始向前搜索,即由后开始向前搜索(J:=J-1),找到第一个小于X的值,两者交换; 4)、从I开始向后搜索,即由前开始向后搜索(I:=I+1),找到第一个大于X的值,两者交换; 5)、重复第3、4步,直到I=J; 例如:待排序的数组A的值分别是:(初始

19、关键数据X:=49) A1 A2 A3 A4 A5 A6 A7: 49 38 65 97 76 13 27 进行第一次交换后: 27 38 65 97 76 13 49 ( 按照算法的第三步从后面开始找)进行第二次交换后: 27 38 49 97 76 13 65 ( 按照算法的第四步从前面开始找X的值,6549,两者交换,此时I:=3 ) 进行第三次交换后: 27 38 13 97 76 49 65 ( 按照算法的第五步将又一次执行算法的第三步从后开始找 进行第四次交换后: 27 38 13 49 76 97 65 ( 按照算法的第四步从前面开始找大于X的值,9749,两者交换,此时J:=4

20、 ) 此时再执行第三步的时候就发现I=J,从而结束一躺快速排序,那么经过一躺快速排序之后的结果是:27 38 13 49 76 97 65,即所以大于49的数全部在49的后面,所以小于49的数全部在49的前面。 快速排序就是递归调用此过程在以49为中点分割这个数据序列,分别对前面一部分和后面一部分进行类似的快速排序,从而完成全部数据序列的快速排序,最后把此数据序列变成一个有序的序列,根据这种思想对于上述数组A的快速排序的全过程如图6所示: 初始状态 49 38 65 97 76 13 27 进行一次快速排序之后划分为 27 38 13 49 76 97 65 分别对前后两部分进行快速排序 27

21、 38 13 经第三步和第四步交换后变成 13 27 38 完成排序76 97 65 经第三步和第四步交换后变成 65 76 97 完成排序 快速排序程序一:procedure quicksort(var b:arr; s,t:integer); var i,j,x,t1:integer; begin i:=s;j:=t;x:=bi; repeat while (bj=x) and (ji) do j:=j-1; if ji then begin t1:=bi; bi:=bj;bj:=t1;end; while (bi=x) and (ij) do i:=i+1; if ij then beg

22、in t1:=bj;bj:=bi;bi:=t1; end until i=j; bi:=x; i:=i+1;j:=j-1; if sj then quicksort(b,s,j); if it then quicksort(b,i,t); end; 快速排序二:这个例程中假设待排序的数组是全局变量a。procedure qsort(s,t:longint);var i,j,x,temp:longint;begini:=s; j:=t; x:=a(i+j)div 2; / x 是中间项值repeat while a i x do dec(j);找右边比他小的 if ij;if sj then q

23、sort(s,j);if it then qsort(i,t);end;注意j小于i, 这种快速排序不同于标准快排,它不是将数列分成以主元为参照的两组子数列(左小右大),而是将数列分成两部分,左侧数字右侧数字(参照值是中间值)(7)取余计算源程序名 mod.?(pas, c, cpp)可执行文件名 mod.exe输入文件名 mod.in输出文件名 mod.out【问题描述】 输入b,p,k的值,求b p mod k的值。其中b,p,k*k为长整型数。【样例】 mod.in mod.out 2 10 9 210 mod 9=7【知识准备】 进制转换的思想、二分法。【算法分析】 本题主要的难点在于

24、数据规模很大(b, p都是长整型数),对于bp显然不能死算,那样的话时间复杂度和编程复杂度都很大。 下面先介绍一个原理:a*b mod k(a mod k)*(b mod k)mod k。显然有了这个原理,就可以把较大的幂分解成较小的,因而免去高精度计算等复杂过程。那么怎样分解最有效呢?显然对于任何一个自然数P,有p2*p div 2+p mod 2,如192*19 div 2十19 mod 22*9+1,利用上述原理就可以把b的19次方除以k的余数转换为求b的9次方除以k的余数,即b19=b2*9+1b*b9*b9,再进一步分解下去就不难求得整个问题的解。 这是一个典型的分治问题,具体实现的

25、时候是用递推的方法来处理的,如p=19,有19=2*9+1,9=2*4+1,4=2*2+0,2=2*1+0,12*0+1,反过来,我们可以从0出发,通过乘以2再加上一个0或1而推出1,2,4,9,19,这样就逐步得到了原来的指数,进而递推出以b为底,依次以这些数为指数的自然数除以k的余数。不难看出这里每一次乘以2后要加的数就是19对应的二进制数的各位数字,即1,0,0,1,1,而19(10011)2,求解的过程也就是将二进制数还原为十进制数的过程。 (8)麦森数源程序名 mason.?(pas, c, cpp)可执行文件名 mason.exe输入文件名 mason.in输出文件名 mason.

26、out【问题描述】 形如2p-1的素数称为麦森数,这时P一定也是个素数。但反过来不一定,即如果P是个素数,2p-1不一定也是素数。到1998年底,人们已找到了37个麦森数。最大的一个是P=3021377,它有909526位。麦森数有许多重要应用,它与完全数密切相关。 任务:从文件中输入P(1000P3100000),计算2p-1的位数和最后500位数字(用十进制高精度数表示)。【输入】 文件中只包含一个整数P(1000P3100000)。【输出】 第一行:十进制高精度数2p-1的位数; 第211行:十进制高精度数2p-1的最后500位数字(每行输出50位,共输出10行,不足500位时高位补0); 不必验证2p-1与P是否为素数。【样例】 mason.in 1279 mason.out 386 00000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000 00000000000000104079321946643990819252403273640855 3861526224726670480531911235040360805967336029

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

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