日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

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

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

這里有三個關鍵詞:"直接"、"遞歸實現"、"重復運算"

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

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

它的遞推公式如下:

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

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

首先,我(不是我們)給出 C(m, 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

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

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

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

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

#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)呢?還有,...?

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

好吧,接下來咱采用相同的技術:把結果保存起來

#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

這個就是 所謂的?"自頂向下動態規劃"?。

現在, 我們回到先前 所說的?"楊輝三角"
利用楊輝三角解 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;
}

這個就是 所謂的?"自底向上動態規劃"?。

總結

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

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。