上楼梯问题

来源:互联网 发布:非标设计前景 知乎 编辑:程序博客网 时间:2024/05/01 17:07

上楼梯问题


明明上楼梯有两种方法,每次上一级或者上两级台阶。如果有3级台阶,明明共有3种不同的上楼梯方法:


1 – 1 – 1 每次都上一级
1 – 2      第一次上一级,第二次上两级
2 – 1      第一次上两级,第二次上一级
如果楼梯共有100级,明明有多少种不同的上楼方法呢?

归纳分析
显然此题应该从归纳的角度出发,先从比较小的台阶数量算起:

1 -> 1
2 -> 2
3 -> 3
4 -> 5
接下来分析这些结果的具体情况:


台阶数为1,只有一步上去一种;
台阶数为2,可以每次一阶走两步,也可一步迈两阶,共2种方法;
台阶数为3,第一步可以选择迈一阶或者两阶:如迈一阶,则剩余2阶,后续种数和台阶数为2时相同;如迈两阶,则剩余1阶,后续种数和台阶数为1时相同;
台阶数为4,第一步同样有一阶或两阶的两种走法,后续对应分别是台阶数为2和台阶数为3的情况;
这里我们不难发现,当台阶数大于2后,后面的走法可以通过第一步的选择后变为前面处理过的台阶数,这个定义是递归的。有一定信息学竞赛背景的同学不难发现,这个定义又是需要动态规划的,
因为动态规划最为显著的特点是通过利用前面计算的结果构造最优解,这里面小于100的台阶数都可以被利用到。


而却定了方法后,无论是使用递归或者动态规划,都需要确定边界条件以及状态转移方程。


状态转移方程很显然:设f(n),n为台阶数,对应的函数值表示上楼的方法种数,有


f(n) = f(n-1) + f(n-2)


这样一个状态转移方程。确定了状态转移方程后,边界条件自然就好确定了。


从状态转移方程中看出,函数f的参数为正整数,那么n就要满足n <= 3的这个条件,以保证n-1和n-2为正整数。所以边界条件有2个,分别是当n为1和2时:


f(1) = 1 
f(2) = 2 
有了状态转移方程和边界条件,我们就可以动手实现代码了,这里的动态规划可以使用一个数组分别记录从1阶楼梯,到100阶楼梯的上楼种数,也可以使用两个变量或三个变量进行迭代,以减少程序空间占用。为求程序易读明了,我这里使用了数组的动态规划方法编写代码。


 


程序代码实现
#include <stdio.h>int main(int argc, char *argv[]){    int a[101], n, i;    a[1] = 1; a[2] = 2;    scanf("%d", &n);    for (i=3; i<=n; i++) {        a[i] = a[i-1] + a[i-2];    }    printf("%d\n", a[n]);    return 0;}