题目描述:
第i行有i个数字,每次只能向下或向正右方走,求和最大的路径的和
3
1 5
8 4 3
2 6 7 9
6 2 3 5 1
与贪心算法不同的是,因为每次只能向下或向右走,每次走的方向会导致后面结果发生改变。用动态规划的思想解决。仔细分析可以得到数字与左边数字和上边数字的数量关系,用另一个数组去记录每一个数字的最优结果,遍历全部数据即可得结果。
优化方案:不必每个数字的最优结果都要记录,只需要用一个层数大小的数组dp记录每一层的情况即可。每次从左到右遍历下一层时,最开头的数的最大和由上一层开头数字最大和得来,此时dp[0]+=a[i]。然后下一个数据要么由新的dp[i]得来,要么由旧的dp[i]得来。
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <queue>
#include <stack>
#include <string.h>
#include <math.h>
#include <algorithm>
int n;
int tower[40010],value[40010],st[1000];
int main(){
scanf("%d",&n);
for(int i=0;i*(i+1)/2<=n;i++)
st[i]=i*(i+1)/2;
for(int i=1;i<=n;i++){
scanf("%d",&tower[i]);
}
int maxn=-1;
value[1]=tower[1];
for(int i=2;i*(i+1)/2<=n;i++){
value[st[i-1]+1]=value[st[i-2]+1]+tower[st[i-1]+1];
if(value[st[i-1]+1]>maxn)maxn=value[st[i-1]+1];
for(int j=2;j<i;j++){
int t;
if(value[j-1+st[i-1]]>value[j+st[i-2]]){
t=value[j-1+st[i-1]];
}
else{
t=value[j+st[i-2]];
}
printf("+++%d %d %d %d %d",tower[j+st[i-1]],t,i,j,st[i]);
value[j+st[i-1]]=t+tower[st[i-1]+j];
if(value[j+st[i-1]]>maxn)
maxn=value[j+st[i-1]];
}
value[st[i]]=value[st[i]-1]+tower[st[i]];
if(value[st[i]]>maxn)maxn=value[st[i]];
}
for(int i=1;i<=n;i++)
printf("%d**\n",value[i]);
printf("%d\n",maxn);
}