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

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

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

發(fā)布時(shí)間:2023/12/1 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 数字三角形——递归、递推、记忆化搜索 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

數(shù)字三角形

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

問(wèn)題:?? ?
?? ????? 從第一行的數(shù)開(kāi)始,每次可以往左下或右下走一格,直到走到最下行,把沿途經(jīng)過(guò)的數(shù)全部加起來(lái)。如何走才能使得這個(gè)和盡量大?


分析:

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



最先想到的是遞歸實(shí)現(xiàn):

#include "stdio.h" #define maxn 100 int a[maxn][maxn],n;inline max(int x,int y) {return x>y?x:y; }//遞歸計(jì)算實(shí)現(xiàn) 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; }雖然這樣做是正確的,但時(shí)間效率太低,其原因在于重復(fù)計(jì)算。
??????? 例: 在下列計(jì)算中d(3,2)被重復(fù)調(diào)用 ?

??????????????????? d(2,1)?? 的計(jì)算會(huì)調(diào)用--> d(3,1) , d(3,2)
?? ???????????????? d(2,2) ? 的計(jì)算會(huì)調(diào)用--> d(3,2) , d(3,3)


遞推的實(shí)現(xiàn):

#include "stdio.h" #define maxn 100 int a[maxn][maxn],n;inline max(int x,int y) {return x>y?x:y; }//遞推實(shí)現(xiàn) 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; }


記憶化搜索實(shí)現(xiàn):

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


總結(jié)

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

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