日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Fibonacci数列 递归 杨辉三角 动态规划

發(fā)布時間:2025/6/15 编程问答 14 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Fibonacci数列 递归 杨辉三角 动态规划 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
這篇帖子主要是介紹?遞歸?與 動態(tài)規(guī)劃 之間是如何轉(zhuǎn)換的,
什么是遞歸估計不用多說,那么什么是?動態(tài)規(guī)劃呢?
我理解的動態(tài)規(guī)劃就是:
能夠避免 直接 遞歸實現(xiàn) 中出現(xiàn)的重復運算的技術(shù)就是動態(tài)規(guī)劃。

這里有三個關(guān)鍵詞:"直接"、"遞歸實現(xiàn)"、"重復運算"

也許最簡單的, 也是眾所周知的動態(tài)規(guī)劃題目是?Fibonacci數(shù)列,?
如果你不知道,說明你的老師也不知道,而且我為你感到難過。

但是,遺憾的是,本文將 選取另一個也是眾所周知的動態(tài)規(guī)劃題目:?
二項式系數(shù) C(m, n)

它的遞推公式如下:

C(m, n) = C(m-1, n-1) + C(m-1, n), C(m, 0) = 1, C(m, m) = 1;

你或許會很驚訝,這是什么?我根本不熟悉嘛!
好吧,我想楊輝三角你應(yīng)該不陌生,是個c語言的書籍都會有這道題,
那么,你還記不記得楊輝三角 與 二項式系數(shù)有那么一點點的關(guān)系呢?
記不得,翻書吧!

首先,我(不是我們)給出 C(m, n)的?直接遞歸實現(xiàn)

#include <stdio.h>

int C(int M, int N);

int main(void)
{
??? printf("%d\n", C(5, 2));

??? getchar();

??? return 0;
}

int C(int M, int N)
{
????
??? if (N == 0 || M == N)
??? {
????????return 1;
??? }

??? return C(M-1, N-1) + C(M-1, N);
}

輸出:10

那么, 這個實現(xiàn)直接嗎?
當然直接,公式就是這樣定義的啊。不是嗎?

然后, 可以肯定的是這個實現(xiàn)有 重復運算,
肯定有,要不然不會拿這道題作為例程解析。
怎么樣知道這個實現(xiàn)有 重復運算呢?

很簡單,把遞歸調(diào)用路徑打印出來看一眼就行了,僅僅是一眼。
在此之前,得確信你會 復制/粘帖 控制臺中的內(nèi)容,如果你還不會,
那么,請你百度一下吧。

我給函數(shù)多加一個參數(shù)用來記錄 遞歸調(diào)用深度?(這項技術(shù)已經(jīng)被我多次使用,不知你的技術(shù)敏感度怎么樣,有沒有留意過)?
然后,重新實現(xiàn)一下代碼

#include <stdio.h>

int C(int M, int N, int depth);

int main(void)
{
??? printf("\nc(5, 2) = %d", C(5, 2, 0));

??? getchar();

??? return 0;
}
int C(int M, int N, int depth)
{
??? int i, ret;

??? for (i = 0; i < depth; i++)
??? {
????????printf(" ");
??? }

??? printf("C(%d, %d)\n", M, N);

??? if (N == 0 || M == N)
??? {
????????return 1;
??? }

??? return C(M-1, N-1, depth+1) + C(M-1, N, depth+1);
}?

輸出:

C(5, 2)
C(4, 1)
??C(3, 0)
??C(3, 1)
???C(2, 0)
???C(2, 1)
??? C(1, 0)
??? C(1, 1)
C(4, 2)
??C(3, 1)
???C(2, 0)
???C(2, 1)
??? C(1, 0)
??? C(1, 1)
??C(3, 2)
???C(2, 1)
??? C(1, 0)
??? C(1, 1)
???C(2, 2)

c(5, 2) = 10

很明顯的可以看出,C(1, 1)被多次運算過,當然不只是C(1, 1)了, 還有C(2, 1)呢?還有,...?

然后,怎么樣避免這個實現(xiàn)中的重復運算呢?
還記得先前有個帖子 "打家看看這個遞歸的 為什么結(jié)果要存起來 不能直接返回T 求N的階乘的遞歸都不要存結(jié)果" 嗎?

好吧,接下來咱采用相同的技術(shù):把結(jié)果保存起來

#include <stdio.h>

#define M 5
#define N 2

int C(int m, int n, int depth);

int knownC[M+1][N+1] = {0};

int main(void)
{
??? printf("\nc(%d, %d) = %d\n", M, N, C(M, N, 0));
??? getchar();
??? return 0;
}

int C(int m, int n, int depth)
{
??? int i, ret;

??? for (i = 0; i < depth; i++)
??? {
????????printf(" ");
??? }

??? printf("C(%d, %d)\n", m, n);

??? if (knownC[m][n] != 0)
??? {
????????return knownC[m][n];
??? }

??? if (n == 0 || m == n)
??? {
????????ret = 1;
??? }
??? else
??? {
????????ret = C(m-1, n-1, depth+1) + C(m-1, n, depth+1);
??? }

??? return knownC[m][n] = ret;
}

輸出:
C(5, 2)
C(4, 1)
??C(3, 0)
??C(3, 1)
???C(2, 0)
???C(2, 1)
??? C(1, 0)
??? C(1, 1)
C(4, 2)
??C(3, 1)
??C(3, 2)
???C(2, 1)
???C(2, 2)

c(5, 2) = 10

這個就是 所謂的?"自頂向下動態(tài)規(guī)劃"?。

現(xiàn)在, 我們回到先前 所說的?"楊輝三角"
利用楊輝三角解 C(m, n) 。

#include <stdio.h>

#define M 5
#define N 2

int main(void)
{
????
??? int C[M+2][M+2] = {0, 1};
??? int i, j;

??? for (i = 1; i < M+2; i++)
??? {
????????for (j = 1; j <= i; j++)
????????{
????????????C[i][j] = C[i-1][j-1] + C[i-1][j];
????????}
??? }

??? printf("%d\n", C[M+1][N+1]);

??? return 0;
}

這個就是 所謂的?"自底向上動態(tài)規(guī)劃"?。

總結(jié)

以上是生活随笔為你收集整理的Fibonacci数列 递归 杨辉三角 动态规划的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。