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

【例1】数字三角形
如下所示为一个数字三角形。请编一个程序计算从顶到底的某处的一条路径,使该路径所经过的数字总和最大。只要求输出总和。
 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层前进时,我们的选择一定是沿其下两条可行路径中最大数字的方向前进,为此,我们可以采用倒推的手法,设a[i][j]存放从i,j 出发到达n层的最大值,则a[i][j]=max{a[i][j]+a[i+1][j],a[i][j]+a[i+1][j+1]},a[1][1] 即为所求的数字总和的最大值。

#include<iostream>
using namespace std;
int main()
{int n,i,j,a[101][101];cin>>n;for(i=1;i<=n;i++)for(j=1;j<=i;j++) cin>>a[i][j];for(i=n-1;i>=1;i--)for(j=1;j<=i;j++){if(a[i+1][j]>=a[i+1][j+1]) a[i][j]+=a[i+1][j];else a[i][j]+=a[i+1][j+1];}cout<<a[1][1];    return 0;
}
#include<iostream>
using namespace std;
int a[101][101]={0};
int main()
{int n,i,j;cin>>n;for(i=1;i<=n;i++)for(j=1;j<=i;j++) cin>>a[i][j];for(i=2;i<=n;i++)for(j=1;j<=i;j++) {if(a[i-1][j]>=a[i-1][j-1]) a[i][j]+=a[i-1][j];else a[i][j]+=a[i-1][j-1];}int max=0;for(i=1;i<=n;i++)if(a[n][i]>max) max=a[n][i];cout<<max;return 0;
}

【例2】满足F1=F2=1,Fn=F(n-1)+F(n-2)的数列称为斐波那契数列(Fibonacci),它的前若干项是1,1,2,3,5,8,13,21,34……求此数 列第n项(n>=3)。
即:
   f1=1                                    (n=1)
   f2=1                                    (n=2)
   fn=f(n-1) + f(n-2 )      (n>=3)

#include<iostream>
#include<stdio.h>
using namespace std;
int main()
{int n,i,f1=1,f2=1,f;scanf("%d",&n);if(n<=2) cout<<1;else {for(i=3;i<=n;i++){f=f1+f2;f1=f2;f2=f;}}printf("%d",f);return 0;
}

有关Fibonacci数列
楼梯台阶问题
问题:楼梯有n个台阶,上楼可以一步上一阶,也可以一步上两阶。一共有多少种上楼的方法?
这是一道计数问题。在没有思路时,不妨试着找规律。n=5时,一共有8种方法:
5=1+1+1+1+1
5=2+1+1+1
5=1+2+1+1
5=1+1+2+1
5=1+1+1+2
5=2+2+1
5=2+1+2
5=1+2+2
其中有5种方法第1步走了1阶(背景灰色),3种方法第1步走了2阶,没有其他可能。
假设f(n)为n个台阶的走法总数,把n个台阶的走法分成两类。
    第1类:第1步走1阶,剩下还有n-1阶要走,有f(n-1)种方法。
    第2类:第1步走2阶,剩下还有n-2阶要走,有f(n-2)种方法。
    这样,就得到了递推式:f(n)=f(n-1)+f(n-2),不要忘记边界情况:f(1)=1,f(2)=2。
    把f(n)的前几项列出:1,2,3,5,8,……。

兔子产子问题
问题:把雌雄各一的一对新兔子放入养殖场中。每只雌兔在出生两个月以后,每月产雌雄各一的一对新兔子。试问第n个月后养殖场中共有多少对兔子。
找规律:
        第1个月:一对新兔子r1。用小写字母表示新兔子。
        第2个月:还是一对新兔子,不过已经长大,具备生育能力了,用大写字母R1表示。
        第3个月:R1生了一对新兔子r2,一共2对。
        第4个月:R1又生一对新兔子r3,一共3对。另外,r2长大了,变成R2。
        第5个月:R1和R2各生一对,记为r4和r5,共5对。此外,r3长成R3。
       第6个月:R1、R2和R3各生一对,记为r6~r8,共8对。此外,r4和r5长大。
        ……
        把这些数排列起来:1,1,2,3,5,8,……,事实上,可以直接推导出来递推关系f(n)=f(n-1)+f(n-2):第n个月的兔子由两部分组成,一部分是上个月就有的老兔子f(n-1),一部分是这个月出生的新兔子f(n-2)(第n个月时具有生育能力的兔子数就等于第n-2个月兔子总数)。根据加法原理,f(n)=f(n-1)+f(n-2)。

【例3】骨牌的铺法
有 2χn的一个长方形方格,用一个1*2的骨牌铺满方格。编写一个程序,试对给出的任意一个n(n>0), 输出铺法总数。
【算法分析】
(1)面对上述问题,如果思考方法不恰当,要想获得问题的解答是相当困难的。可以用递推方法归纳出问题解的一般规律。
(2)当n=1时,只能是一种铺法,铺法总数有示为x1=1。
(3)当n=2时:骨牌可以两个并列竖排,也可以并列横排,再无其他方法,如下左图所示,因此,铺法总数表示为x2=2;

(4)当n=3时:骨牌可以全部竖排,也可以认为在方格中已经有一个竖排骨牌,则需要在方格中排列两个横排骨牌(无重复方法),若已经在方格中排列两个横排骨牌,则必须在方格中排列一个竖排骨牌。如上右图,再无其他排列方法,因此铺法总数表示为x3=3。
由此可以看出,当n=3时的排列骨牌的方法数是n=1和n=2排列方法数的和。
(5)推出一般规律:对一般的n,要求xn可以这样来考虑,若第一个骨牌是竖排列放置,剩下有n-1个骨牌需要排列,这时排列方法数为xn-1;若第一个骨牌是横排列,整个方格至少有2个骨牌是横排列(1*2骨牌),因此剩下n-2个骨牌需要排列,这是骨牌排列方法数为xn-2。从第一骨牌排列方法考虑,只有这两种可能,所以有:
 xn=x(n-1)+x(n-2)   (n>2)
 x1=1
 x2=2
 xn=xn-1+xn-2就是问题求解的递推公式。任给n都可以从中获得解答。例如n=5,
 x3=x2+x1=3
 x4=x3+x2=5
 x5=x4+x3=8

#include<iostream>
#include<stdio.h>
using namespace std;
int main()
{int n,i,f1=1,f2=2,f;scanf("%d",&n);for(i=1;i<=n;i++){if(i==1) cout<<1<<endl;if(i==2)    cout<<2<<endl;if(i>2){f=f1+f2;cout<<f<<endl;f1=f2;f2=f;}     }return 0;
}

五种典型的递推关系
Ⅰ.Fibonacci数列
在所有的递推关系中,Fibonacci数列应该是最为大家所熟悉的。在最基础的程序设计语言Logo语言中,就有很多这类的题目。而在较为复杂的Basic、Pascal、C语言中,Fibonacci数列类的题目因为解法相对容易一些,逐渐退出了竞赛的舞台。可是这不等于说Fibonacci数列没有研究价值,恰恰相反,一些此类的题目还是能给我们一定的启发的。
Fibonacci数列的代表问题是由意大利著名数学家Fibonacci于1202年提出的“兔子繁殖问题”(又称“Fibonacci问题”)。
问题的提出:有雌雄一对兔子,假定过两个月便可繁殖雌雄各一的一对小兔子。问过n个月后共有多少对兔子?
解:设满x个月共有兔子Fx对,其中当月新生的兔子数目为Nx对。第x-1个月留下的兔子数目设为Fx-1对。则:
      Fx=Nx+ Fx-1
      Nx=F(x-2 )        (即第x-2个月的所有兔子到第x个月都有繁殖能力了)
 ∴   Fx=F(x-1)+F(x-2 )    边界条件:F0=0,F1=1
由上面的递推关系可依次得到
F2=F1+F0=1,F3=F2+F1=2,F4=F3+F2=3,F5=F4+F3=5,……。
Fabonacci数列常出现在比较简单的组合计数问题中,例如以前的竞赛中出现的“骨牌覆盖”问题。在优选法中,Fibonacci数列的用处也得到了较好的体现。

Ⅱ.Hanoi塔问题
问题的提出:Hanoi塔由n个大小不同的圆盘和三根木柱a,b,c组成。开始时,这n个圆盘由大到小依次套在a柱上,如图3-11所示。      要求把a柱上n个圆盘按下述规则移到c柱上:


(1)一次只能移一个圆盘;
(2)圆盘只能在三个柱上存放;
(3)在移动过程中,不允许大盘压小盘。
问将这n个盘子从a柱移动到c柱上,总计需要移动多少个盘次?
解:设hn为n个盘子从a柱移到c柱所需移动的盘次。显然,当n=1时,只需把a 柱上的盘子直接移动到c柱就可以了,故h1=1。当n=2时,先将a柱上面的小盘子移动到b柱上去;然后将大盘子从a柱移到c 柱;最后,将b柱上的小盘子移到c柱上,共记3个盘次,故h2=3。以此类推,当a柱上有n(n>2)个盘子时,总是先借助c柱把上面的n-1个盘子移动到b柱上,然后把a柱最下面的盘子移动到c柱上;再借助a柱把b柱上的n-1个盘子移动到c柱上;总共移动h(n-1)+1+h(n-1)个盘次。
 ∴hn=2h(n-1)+1    边界条件:h1=1

Ⅲ.平面分割问题
问题的提出:设有n条封闭曲线画在平面上,而任何两条封闭曲线恰好相交于两点,且任何三条封闭曲线不相交于同一点,问这些封闭曲线把平面分割成的区域个数。
解:设an为n条封闭曲线把平面分割成的区域个数。 由图3-13可以看出:a2-a1=2;a3-a2=4;a4-a3=6。


从这些式子中可以看出an-a(n-1)=2(n-1)。当然,上面的式子只是我们通过观察4幅图后得出的结论,它的正确性尚不能保证。下面不妨让我们来试着证明一下。当平面上已有n-1条曲线将平面分割成a(n-1)个区域后,第n-1条曲线每与曲线相交一次,就会增加一个区域,因为平面上已有了n-1条封闭曲线,且第n条曲线与已有的每一条闭曲线恰好相交于两点,且不会与任两条曲线交于同一点,故平面上一共增加2(n-1)个区域,加上已有的a(n-1)个区域,一共有a(n-1)+2(n-1)个区域。所以本题的递推关系是an=a(n-1)+2(n-1),边界条件是a0=1。

Ⅳ.Catalan数(卡塔兰数)
Catalan数首先是由Euler在精确计算对凸n边形的不同的对角三角形剖分的个数问题时得到的,它经常出现在组合计数问题中。
问题的提出:在一个凸n边形中,通过不相交于n边形内部的对角线,把n边形拆分成若干三角形,不同的拆分数目用hn表示,hn即为Catalan数。例如五边形有如下五种拆分方案(图3-14),故h5=5。求对于一个任意的凸n边形相应的hn。


Catalan数是比较复杂的递推关系,尤其在竞赛的时候,选手很难在较短的时间里建立起正确的递推关系。当然,Catalan数类的问题也可以用搜索的方法来完成,但是,搜索的方法与利用递推关系的方法比较起来,不仅效率低,编程复杂度也陡然提高。

Ⅴ.第二类Stirling数(斯特林数)
在五类典型的递推关系中,第二类Stirling是最不为大家所熟悉的。也正因为如此,我们有必要先解释一下什么是第二类Strling数。

【定义2】n个有区别的球放到m个相同的盒子中,要求无一空盒,其不同的方案数用S(n,m)表示,称为第二类Stirling数。
下面就让我们根据定义来推导带两个参数的递推关系——第二类Stirling数。
 解:设有n个不同的球,分别用b1,b2,……bn表示。从中取出一个球bn,bn的放法有以下两种:
①bn独自占一个盒子;那么剩下的球只能放在m-1个盒子中,方案数为S2(n-1,m-1);
②bn与别的球共占一个盒子;那么可以事先将b1,b2,……bn-1这n-1个球放入m个盒子中,然后再将球bn可以放入其中一个盒子中,方案数为mS2(n-1,m)。
       综合以上两种情况,可以得出第二类Stirling数定理:
【定理】S2(n,m)=mS2(n-1,m)+S2(n-1,m-1)   (n>1,m1)      边界条件可以由定义2推导出:
S2(n,0)=0;S2(n,1)=1;S2(n,n)=1;S2(n,k)=0(k>n)。
第二类Stirling数在竞赛中较少出现,但在竞赛中也有一些题目与其类似,甚至更为复杂。

小结:通过上面对五种典型的递推关系建立过程的探讨,可知对待递推类的题目,要具体情况具体分析,通过找到某状态与其前面状态的联系,建立相应的递推关系。
【例7】(1998合肥市竞赛复试第二题)同一平面内的n(n500)条直线,已知有p(p>=2)条直线相交于同一点,则这n条直线最多能将平面分割成多少个不同的区域?
解:这道题目与第一部分中的平面分割问题十分相似,不同之处就在于线条的曲直以及是否存在共点线条。由于共点直线的特殊性,我们决定先考虑p条相交于一点的直线,然后再考虑剩下的n-p条直线。首先可以直接求出p条相交于一点的直线将平面划分成的区域数为2p个,然后在平面上已经有k(k>=p)条直线的基础上,加上一条直线,最多可以与k条直线相交,而每次相交都会增加一个区域,与最后一条直线相交后,由于直线可以无限延伸,还会再增加一个区域。所以fm=fm-1+m (m>p),边界条件在前面已经计算过了,是fp=2p。虽然这题看上去有两个参数,但是在实际做题中会发现,本题还是属于带一个参数的递推关系。

递推算法-五种典型的递推关系相关推荐

  1. 五种典型的递推关系——一步一步算法篇

    五种典型的递推关系 1.Fibonacci数列 在所有的递推关系中,Fibonacci数列应该是最为大家所熟悉的.在最基础的程序设计语言Logo语言中,就有很多这类的题目.而在较为复杂的Basic.P ...

  2. 递推算法与递推套路(算法基础篇)

    联系我们:有道技术团队助手:ydtech01 / 邮箱:[ydtech@rd.netease.com] 相信了解算法同学经常会说动态规划太难了,看到题目完全不知从何下手,或者是说"一看题解就 ...

  3. 递推算法与递推套路(手撕算法篇)

    联系我们:有道技术团队助手:ydtech01 / 邮箱:[ydtech@rd.netease.com] 之前学习基础知识的时候也说了,递推和动态规划有这暧昧不清的关系,可以说,动态规划就是多了一个决策 ...

  4. C语言经典递推算法之杨辉三角展开(详解)

    文章目录 一.递推算法 二.杨辉三角展开 一.递推算法 这是一种比较简单的算法,即通过已知条件,利用特定关系得到中间结论,然后得到最后结果的算法.递推算法可以分为顺推和逆推两种. 二.杨辉三角展开 1 ...

  5. java递推_Java算法-递推算法思想

    递推算法是常用的算法思想,在数学计算等方面有着广泛的应用.递推算法适合有着明显公式的规律场合. 一.递推算法基本思想 递推算法是一种理性思维模式的代表,其根据已有的数据和关系,逐步推导而得到结果.递推 ...

  6. 递推java_Java算法-递推算法思想

    递推算法是常用的算法思想,在数学计算等方面有着广泛的应用.递推算法适合有着明显公式的规律场合. 一.递推算法基本思想 递推算法是一种理性思维模式的代表,其根据已有的数据和关系,逐步推导而得到结果.递推 ...

  7. 高级IO--1 ---(五种典型IO,阻塞IO,非阻塞IO,信号驱动IO,异步IO, IO多路转接)

    高级IO: 五种典型IO: 阻塞IO/非阻塞IO/信号驱动IO/异步IO/IO多路转接 IO多路转接模型:select/poll/epoll 五种典型IO 阻塞IO IO操作的流程:等待IO操作条件具 ...

  8. 微课|中学生可以这样学Python(8.3节):递推算法例题讲解

    适用教材: 董付国,应根球.<中学生可以这样学Python>.清华大学出版社,2017. 第8章  常用算法的Python实现 8.3  递推算法案例分析 京东购买链接:https://i ...

  9. 递推算法(以数字三角形为例)

    递推算法(以数字三角形为例) 数字三角形.如下所示为一个数字三角形.请编一个程序计算从顶到底的某处的一条路径,使该路径所经过的数字总和最大.只要求输出总和. 1. 一步可沿左斜线向下或右斜线向下走: ...

最新文章

  1. 华为主题包hwt下载_华为手机非官方主题应用指南
  2. 利用EntityFramework获得双色球数据库
  3. Java BufferedReader mark()方法与示例
  4. 【codevs2516】【BZOJ2461】符环,DP
  5. 银行软件测试工作量分析和评估方法(转)
  6. java 开发者异常处理_Java异常处理和设计
  7. 下拉框只读的时候没有下拉图标_百度下拉框营销秘密是什么
  8. 签到活动 测试要点分析
  9. 模型量化 pytorch2onnx
  10. 关于程序员秃顶和预防的小知识
  11. 学习笔记 JavaScript 动画 加速
  12. 子、辰、卯、酉、午、辰时是几点到几点钟「知识普及」
  13. 为什么气象站和 AI 都测不准天气?
  14. keras读取后缀名为.h5的文件
  15. 2015acm区域赛北京
  16. linux禁用usb的命令,禁用linux中的usb端口
  17. Painter not active
  18. [Windows系统]“ppt无法打开演示文稿,防病毒程序可能阻止您打开此演示文稿?”这种情况不要慌
  19. 12306订票助手java_开源免费Java Swing C/S版本12306订票助手
  20. 51单片机直流电机c语言基础知识要点,完结单片机基础知识的总结(制作作品)...

热门文章

  1. textarea不显示边框_飞利浦256P1FR显示器评测:QHD分辨率微窄边设计
  2. RAD PDF 高性能在线编辑|浏览|打印
  3. 微博论道:那些用户行为影响你的站点不被k呢?
  4. 当代大学生想进入IT行业,要做好哪些准备呢?
  5. mysql查询去重第一条,mysql 去重留一
  6. http://www.narkii.com/club/forum-46-1.html 纳金学习论坛,主要是讨论一些unty3D方面的事情,技术栈比较前沿,...
  7. matplotlib绘制常见统计图
  8. Android NDK cannot locate symbol __register_atfork的一次经典定位分析~
  9. 运维人,你应该了解的三张武功心法图
  10. 2016中国电影票房增长跌至个位数,原因何在?