在這樣一棵奇怪的樹中,每次王木木把一棵彈珠放在最上面的根上,然後讓彈珠自由落體,彈珠有可能往左走,也有可能往右走,每次經過一個點,得分加上這個點的價值,那麼王木木最多能得多少分呢?
多組數據輸入
每組數據第一行爲正整數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.這樣遞歸計算,大量的子問題需要重複計算。可以採用帶備忘的自頂向下法,此方法在遞歸過程中保存每一個子問題的解,在求解每個子問題時,如果子問題已求解,直接返回保存子問題的值,可大量減少計算時間。