计蒜客题库爬楼梯(时间不超限制的递归)C++

今天做计蒜客oj上一道题目爬楼梯比较有意思

  •  65536K

假设你现在正在爬楼梯,楼梯有 nn 级。每次你只能爬 11 级或者 22 级,那么你有多少种方法爬到楼梯的顶部?

输入格式

第一行输入一个整数 n(1\leq n \leq 50)n(1n50),代表楼梯的级数。

输出格式

输出爬到楼梯顶部的方法总数。

样例输入

5

样例输出

8

我们来找一下规律吧

如果走一级楼梯,那么只有1这一种走法

走两级楼梯,那么有(11),2这样的两种走法

走三级楼梯,那么有(111),(12),(21)三种走法

走四级楼梯,那么有(1111),(121),(112),(211),(22)五种不同的走法。

以此类推。。。。。。。

我们可以发现是不是和递归里面的斐波罗契数列很想,没错就是f(n)=f(n-1)+f(n-2)这样子的递归函数。

但是题目给出测试条件是1到50你会发现超过40以后程序运行时间会变得很慢,在oj上是通过不了的,比如下面就是时间超限的代码:

#include<iostream>
using namespace std;
int num;


long long dp(int n)
{

    if(n==1) return 1;

        else if(n==2) return 2;

         else return dp(n-1)+dp(n-2);

}


int main()
{
cin>>num;
cout<<dp(num)<<endl;
return 0;

}

这个程序是通过不了的,因为时间超出限制,因为如果输入数据过大时O(2^50)是通过不了的

看下改进代码:

#include<iostream>
using namespace std;
int num;
long long DP[51];


long long dp(int n)
{
    DP[0]=0;
    DP[1]=1;
    DP[2]=2;
    for(int i=3;i<=n;i++)
    {
    DP[i] = DP[i-1]+DP[i-2];
    }
    return DP[n];
}


int main()
{
cin>>num;
cout<<dp(num)<<endl;
return 0;

}

我在这里定义了一个数组用来存放爬楼梯的方法数,那么,为什么这样做就可以减少运行时间,因为之前的递归,每一次都会去重复计算类似dp(6)=dp(5)+dp(4)

dp(5)=dp(4)+dp(3)

dp(4)=dp(3)+dp(2)

那么我们可以看出来每次调用都会重复计算,比如我要计算dp(6)那么我需要计算dp(4)和dp(5),我计算d(5)的时候我需要知道dp(4)和dp(3),我计算dp(3)时需要dp(1)和dp(2)的值,现在因为每一次计算都没有存储,像dp(5)需要dp(3)的值,我在计算dp(4)的时候也需要dp(3)的值,dp(3)的值之前就已经计算过了,因为没有存储,所以每次需要用的时候又要重复计算一便,所以我们定义数组存储,就避免了重复计算,省去了一大把浪费时间。

猜你喜欢

转载自blog.csdn.net/lytwy123/article/details/80818409