1. 程式人生 > >動態規劃:青蛙跳臺階、變態跳臺階

動態規劃:青蛙跳臺階、變態跳臺階

青蛙跳臺階問題是一個簡單的動態規劃問題。

問題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);
}