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 <stdio.h> 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; }