动态规划:青蛙跳台阶、变态跳台阶

来源:互联网 发布:java汽车租赁项目 编辑:程序博客网 时间:2024/06/06 01:47

青蛙跳台阶问题是一个简单的动态规划问题。

问题1:普通跳台阶

一只青蛙可以一次跳 1 级台阶或者一次跳 2 级台阶,例如:

  1. 跳上第 1 级台阶只有一种跳法:直接跳 1 级即可。
  2. 跳上第 2 级台阶有两种跳法:每次跳 1 级,跳两次;或者一次跳 2 级。

问要跳上第 n 级台阶有多少种跳法?

很多人喜欢正向思考,使用暴力求解,但往往这是一个很复杂的问题。我们可以反过来思考:

如果我们要跳上第 n 级台阶,该怎么跳?此时问题就简单多了,答案是,要么从第 n1 级台阶跳一级上来,要么从第 n2 级台阶跳两级上来,除此,青蛙再也没有其他的方法可以跳上第 n 级台阶。

我们令 f(n) 表示从第一级台阶跳上第 n 级台阶有几种跳法。则有如下递推公式:

f(n)=f(n1)+f(n2)

是不是很熟悉,它不就是斐波那契数列吗,代码就很简单啦:

int jumpFloor(int number) {    int g = 1, f = 2;    while (number-- > 1) {        f += g;        g = f - g;    }    return g;}

问题2:变态跳台阶

变态跳台阶问题是这样的:如果青蛙可以一次跳 1 级,也可以一次跳 2 级,一次跳 3 级,…,一次跳 n 级。问要跳上第 n 级台阶有多少种跳法?

同样的,我们采用逆向思维,将问题改为:跳上第 n 级台阶该怎么跳?答案如下:

要跳上第 n 级台阶,可以从第 n1 级台阶一次跳上来,也可以可以从第 n2 级台阶一次跳上来,也可以可以从第 n3 级台阶一次跳上来,…,也可以可以从第 1 级台阶一次跳上来。那么问题就很简单啦,同样的,令 f(n) 表示从第一级台阶跳上第 n 级台阶有几种跳法。则有如下递推公式:

f(n)=f(n1)+f(n2)+...+f(1)

同时,f(n1) 也可以表示如下:
f(n1)=f(n2)+f(n3)+...+f(1)

所以,由上面两个公式可知:
f(n)=2f(n1)=4f(n2)=8f(n3)=...

即:
f(n)=2f(n1)=22f(n2)=23f(n3)=...=2n1f(n(n1))=2n1f(1)

因为 f(1)=1,所以 f(n)=2n1

代码如下:

int square(int a) { return a * a; }int power2(int n) { // 计算2的n次方    if (0 == n) return 1;    return n % 2 ? square(power2(n>>1))<<1 : square(power2(n>>1));}int jumpFloorII(int number) {    return power2(number - 1);}
0 0
原创粉丝点击