從前有一個很可愛的小學生叫作小明,小明平時最大的愛好就是思考問題。
有一天,小明走到了教學樓的臺階前,小明心想:「來學校上學都有好幾天了,居然沒有數過每一層有多少臺階」,而後他就開始數了起來:
一、二、……
「一共有10個臺階!」
數完了臺階,小明開開心心地上臺階了。但是小明邊上臺階,他又邊思考呀:「我每次跨一步能夠上一級臺階,也能夠上二級臺階,再用力跨的話還能夠上三級臺階。那麼我從最底下的地面走到最上層的10級臺階,有多少方案數呢?」
這個問題引發了小明的思考,可是小明是一個勤于思考的好學生,他絕對不會讓一個問題難倒他的。
小明因而開始對這個問題進行全面的思考:
假設我如今站在臺階前,我所在的地面是第0層臺階,我能夠到達的臺階分別是第一、二、三、……、10層臺階,那麼這個問題就變成了:
「請問從第0層臺階開始,每次能夠走一、2或3層臺階,最終到達第10層臺階的方案數有多少種?」
而後小明開始思考:
從第0層臺階走到第0層臺階的方案數一共有1種(由於小明如今就站在第0層臺階上,因此它不須要懂就能到達第0層臺階,也就是說只有1種方案)。
從第0層臺階走到第1層臺階的方案數一共有1種:
0 --> 1 (表示從第0層臺階走到第1層臺階,下同)
從第0層臺階走到第2層臺階的方案數一共有2種:
0 --> 2 (表示直接從第0層臺階跨到了第2層臺階)
0 --> 1 --> 2 (表示先從第0層臺階跨到了第1層臺階,再從第1層臺階跨到了第2層臺階)
從第0層臺階走到第3層臺階的方案數一共有4種:
0 --> 3
0 --> 2 --> 3
0 --> 1 --> 3
0 --> 1 --> 2 --> 3
從第0層臺階走到第4層臺階的方案數一共有7種:
0 --> 3 --> 4
0 --> 2 --> 3 --> 4
0 --> 1 --> 3 --> 4
0 --> 1 --> 2 --> 3 --> 4
0 --> 2 --> 4
0 --> 1 --> 2 --> 4
0 --> 1 --> 4
……
小明很是仔細地列舉出了從第0層臺階到第0、一、二、三、4層臺階的全部方案數,可是當小明開始列舉從第0層臺階到第5層臺階的時候他戛然而止。「不行,這不是我理想種解決問題的方案。若是按照這種方案算到第10層,不只容易漏掉方案致使算錯,還會花費大量時間,在課間十分鐘的時間內我是絕對算不完的!」
於此同時,小明也發現了方案數之間的規律。
假設F(i)表示小明從第0層臺階走到第i層臺階的方案數,那麼,能夠得出下面的規律:
F(0) = 1
F(1) = F(0) = 1
F(2) = F(1) + F(0) = 1 + 1 = 2
而對於全部知足3<=n<=10的n來講,能夠獲得:
F(n) = F(n-1) + F(n-2) + F(n-3)
因而,咱們能夠按照這個公式來得出解決方案以下:
F(3) = F(2) + F(1) + F(0) = 2 + 1 + 1 = 4
F(4) = F(3) + F(2) + F(1) = 4 + 2 + 1 = 7
F(5) = F(4) + F(3) + F(2) = 7 + 4 + 2 = 13
F(6) = F(5) + F(4) + F(3) = 13 + 7 + 4 = 24
F(7) = F(6) + F(5) + F(4) = 24 + 13 + 7 = 44
F(8) = F(7) + F(6) + F(5) = 44 + 24 + 13 = 81
F(9) = F(8) + F(7) + F(6) = 81 + 44 + 24 = 149
F(10) = F(9) + F(8) + F(7) = 149 + 81 + 44 = 274
因而,小明在上課預備鈴想的那一刻,計算出了從第0層臺階到第10層臺階的方案數是274種,開開心心地去上課了。算法
趁小明去上課的時間,在這裏和你們簡要地闡述一下小明解決爬樓梯問題地算法,那就是「動態規劃」了。
拿爬樓梯地問題來講,咱們把到達某一層樓梯都設爲一種狀態,用F(i)來表示從第0層臺階爬到第i層臺階地方案數,那麼咱們能夠發現,F(i)和F(i-1)、F(i-2)以及F(i-3)都是有聯繫的,進一步推敲他們之間的關係,咱們即可以得出下面的公式:
F(n) = F(n-1) + F(n-2) + F(n-3)
像這樣的公式咱們通常把它叫作「狀態轉移方程」,而像這種通常能夠用狀態轉移方程進行求解問題的方法咱們就把它們稱爲「動態規劃」了。
如今,你是否是對動態規劃有了一個大體的瞭解了呢:)spa
求解上述問題的C++代碼:code
#include <cstdio> int f[11]; int main() { f[0] = f[1] = 1; f[2] = f[1] + f[0]; for (int i = 3; i <= 10; i ++) { f[i] = f[i-1] + f[i-2] + f[i-3]; } printf("%d\n", f[10]); return 0; }