CCF NOI1072 爬楼梯

问题链接:CCF NOI1072 爬楼梯




时间限制: 1000 ms  空间限制: 262144 KB

题目描述 

  树老师爬楼梯,他可以每次走1级或者2级,输入楼梯的级数,求不同的走法数。例如:楼梯一共有3级,他可以每次都走一级,或者第一次走一级,第二次走两级,也可以第一次走两级,第二次走一级,一共3种方法。

输入

  输入包含若干行,每行包含一个正整数N(1<=N<=30),代表楼梯级数。

输出

  不同的走法数,每一行输入对应一行输出。

样例输入

5

8

10

样例输出

8

34

89

数据范围限制

  1<=N<=30




问题分析

  这是一个递推的问题。站在楼梯的第n级想一下,前一步是从哪里来的,问题就清楚了。

  由于每次只能上一级或两级,那么f(n)=f(n-2)+f(n-1)。这不就是一个菲波拉契数列吗?就是一个递推问题?

  可是,开始时候是站在第1级台阶上,所以数列的开始几项会有所不同。

  f(1)=0,因为开始就站在第1级台阶上;

  f(2)=1,只能从第1级台阶上1级;

  f(3)=2,只能从第1级台阶上2级,或只能从第2级台阶上1级;

  f(n)=f(n-2)+f(n-1),n>3。

  得到上述递推关系后,便可以写了一个函数来计算f(n)。

  测试用例可能很多,所以必须打表。

程序说明

  函数setstairs()计算数列的各个项存储在数组stairs[]中备用,函数是用递推来实现。

要点详解
  • 用函数封装功能是一个好的做法
  • 能用递推就不用递归,递归的代码逻辑往往比递推要简洁,但是通常时间上要慢并且需要更多的存储。
  • 重复多次使用计算函数值时,如果函数是递归定义的,简单地封装函数会导致重复计算,通常用打表的方法来解决。这是一种套路,需要熟练掌握。



参考链接:HDU2041 超级楼梯。

100分通过的C语言程序:

#include 

typedef unsigned long long ULL;

#define N 30

ULL stairs[N+1];

void setstairs(int n)
{
    ULL s1=1, s2=2, temp;

    stairs[0] = 0;
    stairs[1] = 1;
    stairs[2] = 2;

    for(int i=3; i<=n; i++) {
        temp = s1 + s2;
        s1 = s2;
        s2 = temp;

        stairs[i] = s2;
    }
}

int main(void)
{
    int n;

    setstairs(N);

    while(scanf("%d", &n) != EOF)
        printf("%lld\n", stairs[n]);

    return 0;
}



你可能感兴趣的:(#,NOI题解-IV级(CCF),递推递归与组合)