數字三角形

https://biancheng.love/problem/493/index

在這樣一棵奇怪的樹中,每次王木木把一棵彈珠放在最上面的根上,然後讓彈珠自由落體,彈珠有可能往左走,也有可能往右走,每次經過一個點,得分加上這個點的價值,那麼王木木最多能得多少分呢?

多組數據輸入

每組數據第一行爲正整數n(0

#include <cstdio> 
int a[1002][1002]; 
int n;
int sum( int s, int j) 
{ 
    if(s==n) 
        return a[s][j]; 
    int s1 = sum(s+1, j); 
    int s2 = sum(s+1, j+1); 
    if(s1>s2) 
        return s1+a[s][j]; 
    return s2+a[s][j]; 
 } 
int main() 
{ 
    while(~scanf("%d", &n)){
        for( int i = 1; i <= n; i ++ ) 
            for( int j = 1; j <= i; j ++ ) 
                scanf("%d", &a[i][j]); 
        printf("%d\n", sum(1, 1)); 
    }
 }

採用遞歸的方法。用sum(i,j)表示從第i行的第j個數字開始走到底邊最佳路徑和
從某點d[i][j]出發,下一步可以走到d[i+1][j]或者d[i+1][j+1],如果選擇走d[i+1][j]
sum[i][j]=sum[i+1][j]+d[i][j],如果選擇走d[i+1][j+1],sum[i][j]=sum[i+1][j+1]+d[i][j].
選擇走那個,只需比較sum[i+1][j]和sum[i+1][j+1]的大小即可。
實現如下:(經OJ評測,TLE)

#include <cstdio> 
#include<cstring>
int a[1002][1002]; 
int b[1002][1002];
int n;
int sum( int s, int j) 
{ 
    if(s==n) 
        return a[s][j]; 
    if(b[s+1][j]==-1){
        int c=sum(s+1,j);
    b[s+1][j]=c;}
    if(b[s+1][j+1]==-1){
        int d=sum(s+1,j+1);
     b[s+1][j+1] = d; }
     if(b[s+1][j]>b[s+1][j+1]) 
         return b[s+1][j]+a[s][j]; 
     return b[s+1][j+1]+a[s][j]; 
 } 
int main() 
{ 
    while(~scanf("%d", &n)){
        memset(b,-1,sizeof(b));
        for( int i = 1; i <= n; i ++ ) 
             for( int j = 1; j <= i; j ++ ) 
                scanf("%d", &a[i][j]); 
        printf("%d\n", sum(1, 1)); 
    }
}

2.這樣遞歸計算,大量的子問題需要重複計算。可以採用帶備忘的自頂向下法,此方法在遞歸過程中保存每一個子問題的解,在求解每個子問題時,如果子問題已求解,直接返回保存子問題的值,可大量減少計算時間。

点赞