很经典的小问题,一个人爬楼梯,一次只能爬一阶或两阶,当总共有n阶楼梯时,有几种爬法。
这是一道很明显的递归题目,且无法像一般的动态规划那样列出递推方程,但是思想和动态规划比较类似,从问题的结果出法,逆推整个流程。
思路是这样的,这个人最后成功爬上第n阶之前,只有两种可能,爬了一阶或者两阶,因此此时他总共可拥有的次数,即为他最后爬了一阶情况下原来n-1阶的次数加上最后爬了两阶时原来n-2阶的次数。用这种思路一直向前推,直到原来n-1或n-2为一阶或两阶的情况,这时我们可以计算n=1时,只有一种情况,n=2有两种情况(一下爬了两阶,两次都爬一阶),这就是此递归的结尾。
如果把递归式子写出来,就是dp[n] = dp[n-1] + dp[n-2]
和动态规划递推式子不同的是,这里的dp[]无法在循环中得到值,只能在一次次自我调用中获得数值,因此数组就变成了可以传值的函数,这也是递推和递归的一种巧妙的转变吧。
以下代码用dp[]作为储存子问题最优解(子问题总共的次数)的数组,f()是用来判断的数组。
#include<iostream>
using namespace std;
int dp[50];
int f(int n){
if(n == 1||n == 2){
return n;
}
else{
if(!dp[n-1]) {
dp[n-1] = f(n-1);
}
if(!dp[n-2]){
dp[n-2] = f(n-2);
}
return f(n-1) + f(n-2);
}
}
int main(){
int n, sum;
cout<<"请输入楼梯总数:";
cin>>n;
sum = f(n);
cout<<"总共有"<<sum<<"种走法"<<endl;
return 0;
}