第3章递推算法(c++版)2017副本

上传人:命****币 文档编号:114243968 上传时间:2019-11-10 格式:PPT 页数:24 大小:1.38MB
返回 下载 相关 举报
第3章递推算法(c++版)2017副本_第1页
第1页 / 共24页
第3章递推算法(c++版)2017副本_第2页
第2页 / 共24页
第3章递推算法(c++版)2017副本_第3页
第3页 / 共24页
第3章递推算法(c++版)2017副本_第4页
第4页 / 共24页
第3章递推算法(c++版)2017副本_第5页
第5页 / 共24页
点击查看更多>>
资源描述

《第3章递推算法(c++版)2017副本》由会员分享,可在线阅读,更多相关《第3章递推算法(c++版)2017副本(24页珍藏版)》请在金锄头文库上搜索。

1、第三章 递推算法,递推法是一种重要的数学方法,在数学的各个领域中都有广泛的运用,也是计算机用于数值计算的一个重要算法。这种算法特点是:一个问题的求解需一系列的计算,在已知条件和所求问题之间总存在着某种相互联系的关系,在计算时,如果可以找到前后过程之间的数量关系(即递推式),那么,从问题出发逐步推到已知条件,此种方法叫逆推。无论顺推还是逆推,其关键是要找到递推式。这种处理问题的方法能使复杂运算化为若干步重复的简单运算,充分发挥出计算机擅长于重复处理的特点。 递推算法的首要问题是得到相邻的数据项间的关系(即递推关系)。递推算法避开了求通项公式的麻烦,把一个复杂的问题的求解,分解成了连续的若干步简单

2、运算。一般说来,可以将递推算法看成是一种特殊的迭代算法。,【例1】 有 2n的一个长方形方格,用一个1*2的骨牌铺满方格。,编写一个程序,试对给出的任意一个n(n0), 输出铺法总数。,【算法分析】 (1)面对上述问题,如果思考方法不恰当,要想获得问题的解答是相当困难的。可以用递推方法归纳出问题解的一般规律。 (2)当n=1时,只能是一种铺法,铺法总数有示为x1=1。 (3)当n=2时:骨牌可以两个并列竖排,也可以并列横排,再无其他方法,如下左图所示,因此,铺法总数表示为x2=2;,(4)当n=3时:骨牌可以全部竖排,也可以认为在方格中已经有一个竖排骨牌,则需要在方格中排列两个横排骨牌(无重复

3、方法),若已经在方格中排列两个横排骨牌,则必须在方格中排列一个竖排骨牌。如上右图,再无其他排列方法,因此铺法总数表示为x3=3。 由此可以看出,当n=3时的排列骨牌的方法数是n=1和n=2排列方法数的和。 (5)推出一般规律:对一般的n,要求xn可以这样来考虑,若第一个骨牌是竖排列放置,剩下有n-1个骨牌需要排列,这时排列方法数为xn-1;若第一个骨牌是横排列,整个方格至少有2个骨牌是横排列(1*2骨牌),因此剩下n-2个骨牌需要排列,这是骨牌排列方法数为xn-2。从第一骨牌排列方法考虑,只有这两种可能,所以有: xn=xn-1+xn-2 (n2) x1=1 x2=2 xn=xn-1+xn-2

4、就是问题求解的递推公式。任给n都可以从中获得解答。例如n=5, x3=x2+x1=3 x4=x3+x2=5 x5=x4+x3=8,下面是输入n,输出x1xn的c+程序: #include using namespace std; int main() int n,i,j,a101; coutn; a1=1;a2=2; cout“x1=“a1endl; cout“x2=“a2endl; for (i=3;i=n;i+) /递推过程 ai=ai-1+ai-2; cout“x“i“=“aiendl; 下面是运行程序输入 n=30,输出的结果: input n: 30 x1=1 x2=2 x3=3 x

5、29=832040 x30=1346269 问题的结果就是有名的斐波那契数。,【例2】数字三角形。如下所示为一个数字三角形。请编一个程序计算从顶到底的某处的一条路径,使该路径所经过的数字总和最大。只要求输出总和。 1、 一步可沿左斜线向下或右斜线向下走; 2、 三角形行数小于等于100; 3、 三角形中的数字为0,1,99; 测试数据通过键盘逐行输入,如上例数据应以如下所示格式输入: 5 7 3 8 8 1 0 2 7 4 4 4 5 2 6 5 【算法分析】 此题解法有多种,从递推的思想出发,设想,当从顶层沿某条路径走到第i层向第i+1层前进时,我们的选择一定是沿其下两条可行路径中最大数字的

6、方向前进,为此,我们可以采用倒推的手法,设aij存放从i,j 出发到达n层的最大值,则aij=maxaij+ai+1j,aij+ai+1j+1,a11 即为所求的数字总和的最大值。,【参考程序】 #include using namespace std; int main() int n,i,j,a101101; cinn; for (i=1;iaij; /输入数字三角形的值 for (i=n-1;i=1;i-) for (j=1;j=ai+1j+1) aij+=ai+1j; /路径选择 else aij+=ai+1j+1; couta11endl; ,【例3】棋盘格数 设有一个N*M方格的棋

7、盘( l N100,1M100)。求出该棋盘中包含有多少个正方形、多少个长方形(不包括正方形)。 例如:当 N=2, M3时: 正方形的个数有8个:即边长为1的正方形有6个;边长为2的正方形有2个。 长方形的个数有10个:即2*1的长方形有4个:1*2的长方形有3个:3*1的长方形有2个:3*2的长方形有1个: 程序要求:输入:N,M 输出:正方形的个数与长方形的个数 如上例:输入:2 3 输出:8 10 【算法分析】 1.计算正方形的个数s1 边长为1的正方形个数为n*m 边长为2的正方形个数为(n-1)*(m-1) 边长为3的正方形个数为(n-2)*(m-2) 边长为minn,m的正方形个

8、数为(m-minn,m+1)*(n-minn,m+1) 根据加法原理得出 s1=,2.长方形和正方形的个数之和s 宽为1的长方形和正方形有m个,宽为2的长方形和正方形有m-1个,宽为m的长方形和正方形有1个; 长为1的长方形和正方形有n个,长为2的长方形和正方形有n-1个,长为n的长方形和正方形有1个; 根据乘法原理 s=(1+2+n)*( 1+2+m)=,3.长宽不等的长方形个数s2 显然,s2=s-s1 = -,由此得出算法: #include using namespace std; int main() int n,m; cinmn; int m1=m,n1=n,s1=m*n; /计算

9、正方形的个数s1 while (m1!=0 ,【例4】昆虫繁殖 【问题描述】 科学家在热带森林中发现了一种特殊的昆虫,这种昆虫的繁殖能力很强。每对成虫过x个月产y对卵,每对卵要过两个月长成成虫。假设每个成虫不死,第一个月只有一对成虫,且卵长成成虫后的第一个月不产卵(过X个月产卵),问过Z个月以后,共有成虫多少对?0=X=20,1=Y=20,X=Z=50 【输入格式】 x,y,z的数值 【输出格式】 过Z个月以后,共有成虫对数 【输入样例】 1 2 8 【输出样例】 37,【参考程序】 #include using namespace std; int main() long long a101

10、=0,b101=0,i,j,x,y,z; cinxyz; for(i=1;i=x;i+)ai=1;bi=0; for(i=x+1;i=z+1;i+) /因为要统计到第z个月后,所以要for到z+1 bi=y*ai-x; ai=ai-1+bi-2; coutaz+1endl; return 0; ,【例5】位数问题 【问题描述】 在所有的N位数中,有多少个数中有偶数个数字3?由于结果可能很大,你只需要输出这个答案对12345取余的值。 【输入格式】 读入一个数N 【输出格式】 输出有多少个数中有偶数个数字3。 【输入样例】 2 【输出样例】 73 【数据规模】 1=N=1000 【样例说明】 在

11、所有的2位数字,包含0个3的数有72个,包含2个3的数有1个,共73个,【算法分析】 递推 考虑这种题目,一般来说都是从第i-1位推导第i位,且当前位是取偶数还是取奇数的。 可以用fi0表示前i位取偶数个3有几种情况,fi1表示前i位取奇数个3有几种情况。 则状态转移方程可以表示为: fi0=fi-10*9+fi-11;fi1=fi-10+fi-11*9; 边界条件:f11=1;f10=9;,【参考程序】 #include using namespace std; int main() int f10012,n,i,x; cinn; f11=1;f10=9; for(i=2;i=n;i+) x

12、=f10; if(i=n)x-; fi0=(fi-10*x+fi-11)%12345; fi1=(fi-11*x+fi-10)%12345; coutfn0; return 0; ,【例6】过河卒(Noip2002) 【问题描述】 棋盘上A点有一个过河卒,需要走到目标B点。卒行走的规则:可以向下、或者向右。同时在棋盘上的任一点有一个对方的马(如C点),该马所在的点和所有跳跃一步可达的点称为对方马的控制点,如图3-1中的C点和P1,P8,卒不能通过对方马的控制点。棋盘用坐标表示,A点(0,0)、B点(n, m) (n,m为不超过20的整数),同样马的位置坐标是需要给出的,CA且CB。现在要求你计

13、算出卒从A点能够到达B点的路径的条数。,【算法分析】 本题稍加分析就能发现,要到达棋盘上的一个点,只能从左边过来(我们称之为左点)或是从上面过来(我们称之为上点),所以根据加法原理,到达某一点的路径数目,就等于到达其相邻的上点和左点的路径数目之和,因此我们可以使用逐列(或逐行)递推的方法来求出从起点到终点的路径数目。障碍点(马的控制点)也完全适用,只要将到达该点的路径数目设置为0即可。 用Fij表示到达点(i,j)的路径数目,gij表示点(i, j)有无障碍,gij=0表示无障碍,gij=1表示有障碍。 则,递推关系式如下: Fij = Fi-1j + Fij-1 /i0且j0且gij= 0

14、递推边界有4个: Fij = 0 /gij = 1 Fi0 = Fi-10 /i 0且gi0 = 0 F0j = F0j-1 /j 0且g0j = 0 F00 = 1 考虑到最大情况下:n=20,m=20,路径条数可能会超过231-1,所以要用高精度。,【例7】邮票问题 【问题描述】 设有已知面额的邮票m种,每种有n张,用总数不超过n张的邮票,能从面额1开始,最多连续组成多少面额。(1m100,1n100,1邮票面额255) 【输入格式】 第一行:m,n的值,中间用一空格隔开。 第二行:A1m(面额),每个数中间用一空格隔开。 【输出格式】 连续面额数的最大值 【输入样例】stamp.in 3

15、 4 1 2 4 【输出样例】stamp.out 14,【算法分析】 一看到这个题目,给人的第一感觉是用回溯算法,从面额1开始,每种面额都用回溯进行判断,算法复杂度并不高,但是当m,n取到极限值100时,程序明显超时,因此,回溯算法在这里并不可取。 能否用递推完成呢?我们有一个思路:从面额1开始,建立递推关系方程,就用范例来说吧,面额1,2,4只用1张邮票行了,面额3可以表示为面额1,2的邮票和1+1=2,面额5有两种表示方式min(面额1+面额4,面额2+面额3),照此类推,递推关系方程不难建立,就拿邮票问题来说,以下是递推的一种方法: #include using namespace std; int n,m,i

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 办公文档 > 其它办公文档

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号