青蛙跳台阶

【重点参考】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;
}
可以把n级台阶时的跳法看成是n的函数,记为f(n)。当n>2时,第一次跳的时候就有两种不同的选择:一是第一次只跳1级,此时跳法数目等于后面剩下的n-1级台阶的跳法数目,即为f(n-1);另一种选择是第一次跳2级,此时跳法数目等于后面剩下n-2级台阶的跳法数目,即为f(n-2)。因此,n级台阶的不同跳法的总数 f(n)=f(n-1)+f(n-2) 。分析到这里,不难看出这实际上就是斐波那契数列了。以下是对应的C++代码

#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的大矩形,总共有的方法数。 
样例输入: 

样例输出: 
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;
        }		         
    }


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值