很有意思的一题,递推动态规划,拿到这道题首先我们要想到开一个二维数组存这个三角形,然后我们发现如果这个三角形只有一层的话,到最底层的路线的长度和不就是自己本身么,然后从下向上走,
我们定义maxsum[r][j]—代表的是第r行第j个的路线的最大值
那这个maxsum[r][j]是怎么得来的呢这个是我比较关心的问题,
因为我只能选正下方或者右下方的数,那我肯定得选大的那个加上去我的路线的长度才可以尽可能大
所以状态转移方程可以这样写:
maxsum[r][j]=max(maxsum[r+1][j],maxsum[r+1][j+1])+d[r][j];
根据底层的maxsum[r][j]就是d[r][j]
所以就可以进行判断了
还有就是我是用记忆化递推的,(为了避免重复计算),所以所有的maxsum数组初始化为-1,代表未计算过,如果计算过直接调用就好了
主函数比较简单,所要求的答案就是最顶上的maxsum[1][1];
看一下这个function函数怎么写
/*
d(r,j)-----第r行第j个数字(r,j从1开始)
maxsum(i,j)----从d(i,j)到底边的各条路径中最佳的路径的数字之和
就是只要求maxsum(1,1);
典型的递归问题
d(r,j)出发,下一步只能走d(r+1,j)或者d(r,j+1)
避免重复计算
递归变递推
保存maxsum(i,j)
*/
#include<stdio.h>
#include<algorithm>
using namespace std;
const int maxn=120;
int d[maxn][maxn];
int n;
int maxsum[maxn][maxn];
int function(int i,int j)
{
if(maxsum[i][j]!=-1)
return maxsum[i][j];
if(i==n)
return d[i][j];
else
{
int x=function(i+1,j);
int y=function(i+1,j+1);
maxsum[i][j]=max(x,y)+d[i][j];
}
return maxsum[i][j];
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
for(int j=1;j<=i;j++)
{
scanf("%d",&d[i][j]);
maxsum[i][j]=-1;
}
printf("%d\n",function(1,1));
return 0;
}
加油,厚积而薄发