【重点参考】http://www.cnblogs.com/heyonggang/p/3405089.html
一、题目:一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
这个问题正好符合了斐波那契数列的特点
斐波那契(Fibonacci)数列定义如下:
效率很低的解法:
1
2
3
4
5
6
7
8
9
10
|
long
long
Fibonacci_Solution1(unsigned
int
n)
{
if
(n <= 0)
return
0;
if
(n == 1)
return
1;
return
Fibonacci_Solution1(n - 1) + Fibonacci_Solution1(n - 2);
}
|
改进的算法:从下往上计算。首先根据f(0)和f(1)算出f(2),再根据f(1)和f(2)算出f(3)。。。。。依此类推就可以算出第n项了。很容易理解,这种思路的时间复杂度是o(n)。实现代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
long
long
Fibonacci(unsigned n)
{
int
result[2] = {0 , 1};
if
(n < 2)
return
result[n];
long
long
fibMinusOne = 1;
long
long
fibMinusTwo = 0;
for
(unsigned
int
i = 2 ; i <= n ; ++i)
{
fibN = fibMinusOne + fibMinusTwo;
fibMinusTwo = fibMinusOne;
fibMinusOne = fibN;
}
return
fibN;
}
|
#include<iostream>
#include<iomanip>
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <list>
#include<vector>
#include <cstdio>
#include <iostream>
#include <stack>
#include <queue>
using namespace std;
int jumpFloor(int n) {
if (n == 1)
return 1;
if (n == 2)
return 2;
else if (n>2)
{
long long firstnum = 1;
long long secondnum = 2;
long long fibn = 0;
for (int i = 3; i <= n; i++)
{
fibn = firstnum + secondnum;
firstnum = secondnum;
secondnum = fibn;
}
return fibn;
}
}
int main()
{
int n;
cin >> n;
cout << jumpFloor(n) << endl;
return 0;
}
二、题目转变:在青蛙跳台阶的问题中,如果把条件改成:一只青蛙一次可以跳上1级台阶,也可以跳上2级。。。。。它也可以跳上n级,此时该青蛙跳上一个n级的台阶总共有多少种跳法?
用数学归纳法可以证明f(n)=2n-1.(这个自己可以再好好想想)
思路分析:
青蛙跳上n级台阶的跳法情况(f(n)),第一次跳的时候:
(1) 选择跳上1级台阶,那么还剩下n - 1级台阶,而跳上n – 1级台阶的跳法数目是f(n - 1);
(2) 选择跳上2级台阶,那么剩下n - 2级台阶,而跳上n – 2级台阶的跳法数目是f(n - 2)。
(3)选择跳上3级台阶,剩下n - 3台阶, 而跳上n –3级台阶的跳法数目是f(n - 3)。
……
所以总数为f(n) = f(n-1) + f(n-2) + … + f(2) + f(1) + f(0).
f(n-1)= f(n-2) + … + f(2) + f(1) + f(0)
两式相减得:
f(n) =2f(n-1)
f(1)=1
对于f(0).通过f(2)=f(1)+f(0)=2知道 f(0)=1.
三、换汤不换药的题:矩形覆盖
题目描述:
我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形。请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?
输入:
输入可能包含多个测试样例,对于每个测试案例,
输入包括一个整数n(1<=n<=70),其中n为偶数。
输出:
对应每个测试案例,
输出用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有的方法数。
样例输入:
4
样例输出:
5
思路分析:
重在分析,举例思考
2*n的覆盖方法情况(f(n)),第一个2*1小矩形覆盖最左边的时候:
(1) 第一个2*1小矩形选择竖着放,那么还剩下2*n-1的区域,而2*n-1区域的覆盖数目是f(n - 1);
(2)第一个2*1小矩形选择横着放,则下面必须再放一个2*1小矩形,同时还剩下2*n - 2区域,而2*n-2区域的覆盖数目是f(n - 2);
所以总数为f(n) = f(n-1) + f(n-2) .
f(1)=1
对于f(0).通过f(2)=f(1)+f(0)=2知道 f(0)=1.
public:
int rectCover(int number) {
if(number==0)
{
return 1;
}
if(number==1)
return 1;
else if(number>=2)
{
int first = 1;
int second = 1;
int next=0;
for(int i=2;i<=number;i++)
{
next = first+second;
first = second;
second = next;
}
return next;
}
}