今天做计蒜客oj上一道题目爬楼梯比较有意思
- 65536K
假设你现在正在爬楼梯,楼梯有 nn 级。每次你只能爬 11 级或者 22 级,那么你有多少种方法爬到楼梯的顶部?
输入格式
第一行输入一个整数 n(1\leq n \leq 50)n(1≤n≤50),代表楼梯的级数。
输出格式
输出爬到楼梯顶部的方法总数。
样例输入
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)的值之前就已经计算过了,因为没有存储,所以每次需要用的时候又要重复计算一便,所以我们定义数组存储,就避免了重复计算,省去了一大把浪费时间。