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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

数字三角形——递归、递推、记忆化搜索

發布時間:2023/12/1 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 数字三角形——递归、递推、记忆化搜索 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

數字三角形

描述:
?? ????? 有一個由非負整數組成的三角形,第一行只有一個數,除了最下行之外每個數的左下方和右下方各有一個數。

問題:?? ?
?? ????? 從第一行的數開始,每次可以往左下或右下走一格,直到走到最下行,把沿途經過的數全部加起來。如何走才能使得這個和盡量大?


分析:

?????? 不難看出此題是一個動態的決策問題:每次有兩種選擇——左下或右下。如果用回溯法求出所有的可能的路線,就可以從中選出最優的路線。但和往常一樣,回溯法的效率太低:一個n層數字三角形的完整路線有2^n條,當n很大時回溯法的速度將讓人無法忍受。因此本題討論用遞歸,遞推及記憶化搜索的方法實現,雖然還有其他的方法,但此時只討論學習比較相似的這幾種方法。



最先想到的是遞歸實現:

#include "stdio.h" #define maxn 100 int a[maxn][maxn],n;inline max(int x,int y) {return x>y?x:y; }//遞歸計算實現 int d(int x,int y) {return a[x][y]+(x==n?0:max(d(x+1,y),d(x+1,y+1))); }int main() {while(~scanf("%d",&n)) {int i,j;for(i=1;i<=n;i++){for(j=1;j<=i;j++)scanf("%d",&a[i][j]);}printf("max:%d\n",d(1,1));}return 0; }雖然這樣做是正確的,但時間效率太低,其原因在于重復計算。
??????? 例: 在下列計算中d(3,2)被重復調用 ?

??????????????????? d(2,1)?? 的計算會調用--> d(3,1) , d(3,2)
?? ???????????????? d(2,2) ? 的計算會調用--> d(3,2) , d(3,3)


遞推的實現:

#include "stdio.h" #define maxn 100 int a[maxn][maxn],n;inline max(int x,int y) {return x>y?x:y; }//遞推實現 int d(int x,int y) {int d[n][n],i,j; for(j=1;j<=n;j++) d[n][j]=a[n][j];for(i=n-1;i>=1;i--){for(j=1;j<=i;j++)d[i][j]=a[i][j]+max(d[i+1][j],d[i+1][j+1]);}return d[x][y]; } int main() {while(~scanf("%d",&n)) {int i,j;for(i=1;i<=n;i++){for(j=1;j<=i;j++)scanf("%d",&a[i][j]);} printf("max:%d\n",d(1,1)); }return 0; }


記憶化搜索實現:

#include "stdio.h" #include "string.h" #define maxn 100 int a[maxn][maxn],n; int d[maxn][maxn]; //記憶化搜索所使用的狀態記憶數組 inline max(int x,int y) {return x>y?x:y; }/*記憶話搜索。程序分成兩部分。首先 memset(d,-1,sizeof(d)); 把d全部初始化為-1, 然后編寫遞歸函數: */ int distance(int i,int j) {if(d[i][j]>=0) return d[i][j];return d[i][j]=a[i][j]+(i==n?0:max(distance(i+1,j),distance(i+1,j+1))); } /*上述程序依然是遞歸的,但同時也把計算結果保存在數組d中。題目中說各個數都是非負的,因此 如果已經計算過某個d[i][j],則它應是非負的,這樣,只需把所有d初始化為-1,即可通過判斷是否 d[i][j]>=0得知是否已經被計算過。 */ int main() {while(~scanf("%d",&n)) {int i,j;for(i=1;i<=n;i++){for(j=1;j<=i;j++)scanf("%d",&a[i][j]);}memset(d,-1,sizeof(d)); //狀態記憶化數組初始化 printf("max:%d\n",distance(1,1)); }return 0; }


總結

以上是生活随笔為你收集整理的数字三角形——递归、递推、记忆化搜索的全部內容,希望文章能夠幫你解決所遇到的問題。

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