一个楼梯共有 n级台阶,每次可以走一级或者两级,问从第 0 级台阶走到第 n 级台阶一共有多少种方案。
输入格式
共一行,包含一个整数 n。
输出格式
共一行,包含一个整数,表示方案数。
数据范围
1≤n≤15
输入样例:
5
输出样例:
8
#include <iostream>
//和深度优先搜索时差不多的原理。
using namespace std;
int n;//这里n设在两个函数之外,表示为一个全局变量,因为无论是哪个函数,都需要调用n这个数。
int ans;//用ans来表示走楼梯的方案数,到时候直接输出就行。
void f(int k)/*这个k,表示的是走的级数。观察这个函数你就可以初步的判断,这肯定和递归有关。
传的形参是k,里面的k在不断变化,变化了以后又调用这个函数,就是我们常说的调用自己。
一般来说,我们调用函数,传的形参一般和main函数里面输入的有关,换句话说正常调用函数的时候,这里传的形参应该
是n,而不是k,至于为什么要用递归,为什么要这样写,那就我后面慢慢讲述。*/
{
if (k == n)//当逐步运行得到结果n时,就结束这一路径,然后往回走,直到又找到满足条件的,又继续运行。
ans++;//走到得到n一次,就ans++。
else if (k < n)
{
f(k + 1);/*这个表示函数的调用,是用k+1来替换k然后再次进入函数,不仅计算得到k+1的结果,也会继续
运行里面的判断条件,如果满足这个条件,那ans++,然后就回溯继续运行这个函数里面的语句。
说实话,这玩意是有点绕的,理解起来还是有难度。*/
f(k + 2);
}
}
int main()
{
cin >> n;
f(0);//这里是对k的初始化,表示k刚开始一个台阶也没走,就是0.
cout << ans << endl;
return 0;
}
上面的过程图,就是当n=5时,怎样得到方案数为8的过程。可以发现,k==n时,就不会再接着递归运行了,表示着这一条路已经走完了,就不接着走了,直接ans++就行;从图中可以看出,一条路结束就是一个方案的成功,就直接计数,所以你可以看到,有几个5,那么就有几种方案,所以我才会画圆圈,就是方便计数。
这个图我画的不标准,但是仍然可以看出,这是一个树形结构,这个的学名叫递归搜索树,就是后面算法要接触的深度优先搜索,简称DFS。这个是具体怎么运行的呢,是这样的,只要k<n,那么就k+1或者是k+2,因为题上说了每次走一级或者两级。注意,这个f(k+1)和f(k+2)是一起运行的,不管最后得到的k值是否能满足所给条件,它俩都是同时运行的。
举个例子,当我们第一条路线一直走,走到4这里。因为4<5,所以要执行f(k+1)和f(k+2),这时候k就变成了5和6,但是根据条件,6不满足条件,不写,所以图中才只会有一个5,而没有6;至于f(k+2),k=6不满足条件,那就自动舍去6这个值。我们会发现,一个数下面是有两个k值的,因为走的是两种情况。 当k=3时,先调用函数,算的f(k+1)=4,其实就是把k替换成k+1,调用f(k+1)的时候,进入了函数,得到了结果4,然后又进行if 和else语句的条件判断,这个时候值为4,是等于n的,所以ans++,下面的else语句就不用运行了。到这里还没结束,找到一个方案后,之前是k=3,k+1=4,找到4以后,k值回溯到3,然后继续执行函数里面的语句,然后再进行判断运行。直到最终回溯到根结点0为止,结束。(这只是我现阶段的想法,因为掌握的知识不多,只能理解到这个地步,等到了后面学的东西多了,有了新的理解和感悟,再来补充和改正)。这一过程最好照着上面的过程图去理解,但脑袋里面想还是很有难度的。
递归是一大难点,但是是很重要的一个知识点,在后面的很多算法中均有使用,所以还是多多理解吧,争取掌握它。我写这些过程也很难受,用语言表示还是不好表述,但我还是写了,如有写的不好的地方,还请见谅,毕竟我也只是一个小白。