爬楼梯问题以及拓展
描述
树老师爬楼梯,他可以每次走1级或者2级,输入楼梯的级数,求不同的走法数
例如:楼梯一共有3级,他可以每次都走一级,或者第一次走一级,第二次走两级
也可以第一次走两级,第二次走一级,一共3种方法。
输入
输入包含一行,一行包含一个正整数N,代表楼梯级数,1 <= N <= 5000
输出
不同的走法数,输出该层楼梯的方案数
一般思想:
相当于从终点n梯回到0梯,每次可回一步或两步,f(n)= f(n-1)+ f(n-2)。当回到1梯或2梯时,因为从0梯走到1梯时,只有走一步的方案;从0梯走到2梯时,有两次走一步的方案(方案一),有一次走两步的方案(方案二)。所以当x=1时(即回到1梯时),返回1;当x=2时(即回到2梯时),返回2。
#include<bits/stdc++.h>
using namespace std;
int fun(int x)
{
if(x==1)
{
return 1;
}
if(x==2)
{
return 2;
}
return fun(x-1)+fun(x-2);
}
int main()
{
int n;
scanf("%d",&n);
printf("%d",fun(n));
return 0;
}
这个方法大多数人都能想到,但当N很大的时候,因为递归的调用会随着数的增长时间和空间占用增长巨快,所以一般在数很大的时候这个方法往往爆时或爆空间。
优化:
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 100000;
int prog[MAXN+5];
int main()
{
int n;
scanf("%d",&n);
prog[1] = 1;
prog[2] = 2;
for(int i = 3;i <= n;i++)
{
prog[i] = prog[i-1] + prog[i-2];
}
printf("%d",prog[n]);
return 0;
}
这种方法直接把时间复杂度缩成了O(n),大大减少了递归的时间消耗和空间消耗。
爬楼梯类型问题的拓展
描述
现在小瓜想走上一个一共有n级的台阶,由于小瓜的腿比较短,他一次只能向上走1级或者2级台阶。小瓜想知道他有多少种方法走上这n级台阶,你能帮帮他吗?
输入
一行一个整数n(n<=100000),表示一共有n级台阶。
输出
一行一个整数,表示小瓜上台阶的方案数 对100003取余 的结果。
输入样例(1)
3
输出样例(1)
3
输入样例(2)
81470
输出样例(2)
4367
输入样例(3)
35987
输出样例(3)
36367
显然如果用递归的方法的话,那么此题就应该是凉凉了。
所以要用优化题解
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 100000;
int prog[MAXN+5];
int main()
{
int n;
scanf("%d",&n);
prog[1] = 1;
prog[2] = 2;
for(int i = 3;i <= n;i++)
{
prog[i] = (prog[i-1] + prog[i-2])%100003; //这里是为了数不爆炸,因为结果都是把结果对100003取余,按照提取公因数,提前把数对100003取余是没有影响的。
}
printf("%d",prog[n]);
return 0;
}
完