题目:
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
思路:
采用递归的思想,最后一步可以爬1个或者两个台阶,所以可以得出递归关系:爬n阶台阶的爬法等于爬(n-1)阶台阶和(n-2)阶台阶的爬法之和。
即,f(n)=f(n-1)+f(n-2).
这里也不难看出递归出口是n为1和2的时候,代码如下,可供参考:
int fun(int n) //爬楼梯总的方法数
{if(n==1){return 1;}else if(n==2){return 2;}else{return fun(n-1)+fun(n-2);}
}
爬台阶问题看似简单,但是其实它的扩展确实有些出人意料,在蓝桥杯的时候就有曾考到偶数步爬楼梯问题,即偶数步爬完楼梯的爬法。
算法最重要的还是思想,没有那种思想,可能想很长时间都不一定能有思路。
受到老师的启发,发现了一种递归求解的方法。
思想:偶数步可以推广到最后两步,f(n)代表爬到第n阶楼梯的偶数步爬法,推广到最后两步,可以确保一定为偶数步。
两步可以有三种情况,
f(n-2) 1 1 (最后两阶都爬一阶)
f(n-4) 2 2 (最后两阶都爬两阶)
f(n-3) 1 2或者 2 1(先爬一阶或者先爬两阶)
即f(n)=f(n-2)+f(n-4)+2*f(n-3)
这里f(n-3)为什么要乘以2呢,是因为这种情况的最后两步有两种爬法。
由n>=0,也不难推出递归的出口是n为1到4的情况,这里不多继续叙述,代码如下:
int funEven(int n) //偶数爬楼梯的方法数
{if(n==1){return 0;}else if(n==2){return 1;}else if(n==3||n==4){return 2;}else{return funEven(n-2)+funEven(n-4)+funEven(n-3)*2;}
}
剩下的就是奇数步的扩展了,思想和偶数差不多,看着代码自己悟出自己的思路才是最关键的。
这里直接给出一个最终的测试代码文件,仅供参考。
#include<iostream>
#include<bits/stdc++.h>
using namespace std;int fun(int n);
int funOdd(int n);
int funEven(int n); int main()
{int n;cout<<"请输入楼梯阶数:";cin>>n;cout<<"一共有"<<fun(n)<<"种爬法"<<endl;cout<<"偶数步爬楼梯一共有"<<funEven(n)<<"种爬法"<<endl;cout<<"奇数步爬楼梯一共有"<<funOdd(n)<<"种爬法"<<endl;}int fun(int n) //爬楼梯总的方法数
{if(n==1){return 1;}else if(n==2){return 2;}else{return fun(n-1)+fun(n-2);}
}int funOdd(int n) //奇数爬楼梯的方法数
{if(n==1){return 1;}else if(n==2){return 1;}else if(n==3){return 1;}else if(n==4){return 3;} else{return funOdd(n-2)+funOdd(n-4)+funOdd(n-3)*2;}
}int funEven(int n) //偶数爬楼梯的方法数
{if(n==1){return 0;}else if(n==2){return 1;}else if(n==3||n==4){return 2;}else{return funEven(n-2)+funEven(n-4)+funEven(n-3)*2;}
}
在博客园里也看到不少大佬在做那道蓝桥杯的题目时有其他的思路,感觉很巧妙,不过感觉自己的思想还没转到那一步,等的熟练掌握了会继续更新。
受尽苦难,不负野心。
这就是挚爱索隆的最强剑道。