算法设计与分析——第二章_递推算法

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

  递推算法的首要问题是得到相邻的数据项间的关系(即递推关系)。递推算法避开了求通项公式的麻烦,把一个复杂的问题的求解,分解成了连续的若干步简单运算。一般说来,可以将递推算法看成是一种特殊的迭

1】数字三角形。如下所示为一个数字三角形。请编一个程序计算从顶到底的某处的一条路径,使该路径所经过的数字总和最大。只要求输出总和。

    1、 一步可沿左斜线向下或右斜线向下走;

    2、 三角形行数小于等于100

       3、 三角形中的数字为0199

    测试数据通过键盘逐行输入,如上例数据应以如下所示格式输入:

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]<<endl;

}

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

  程序如下:
  #include< iostream >
  #include< cstdio >
  using namespace std ;
  int main()
  {
      int f0=1,f1=1,f2;
      int n;
      cin>>n;
  for (int i=3; i<=n; ++i)
      {
           f2=f0+f1;
           f0=f1;
           f1=f2;
      }
  printf("%d\n",f2);
  return 0;
  }

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=1n=2排列方法数的和。

   (5)推出一般规律:对一般的n,要求xn可以这样来考虑,若第一个骨牌是竖排列放置,剩下有n-1个骨牌需要排列,这时排列方法数为xn-1;若第一个骨牌是横排列,整个方格至少有2个骨牌是横排列(1*2骨牌),因此剩下n-2个骨牌需要排列,这是骨牌排列方法数为xn-2。从第一骨牌排列方法考虑,只有这两种可能,所以有:

             xn=xn-1+xn-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

下面是输入n,输出x1~xnc++程序:

#include<iostream>

using namespace std;

int main()

{

  int n,i,j,a[101];

  cout<<"input n:";                     //输入骨牌数

  cin>>n;

  a[1]=1;a[2]=2;

  cout<<"x[1]="<<a[1]<<endl;

  cout<<"x[2]="<<a[2]<<endl;

  for (i=3;i<=n;i++)                //递推过程

   {

     a[i]=a[i-1]+a[i-2];

     cout<<"x["<<i<<"]="<<a[i]<<endl;

    }

}

  下面是运行程序输入 n=30,输出的结果:

   input n: 30

      x[1]=1

      x[2]=2

      x[3]=3

  ........

      x[29]=832040

      x[30]=1346269

问题的结果就是有名的斐波那契数。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值