题目描述
考虑在下面被显示的数字金字塔。 写一个程序来计算从最高点开始在底部任意处结束的路径经过数字的和的最大。每一步可以走到左下方的点也可以到达右下方的点。
在上面的样例中,从7 到 3 到 8 到 7 到 5 的路径产生了最大和:30
输入
第1行:1个整数R(1<= R<=1000),表示行的数目。
接下来共R行,第i行有i个整数。所有的数均非负的且不大于100。
输出
第1行:可以得到的最大的和。
样例输入
5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
样例输出
30
【分析】
这一题如果用贪心法来做,有可能得不到最优解。如果用枚举,列举的路径会有很多。所以可以用动态规划来解题。
因为只能走左下或右下,所以只需要判断走哪一边能使数之和最大。走了那一边之后又到了一个新点,再判断走哪边能使数之和最大。所以,只需要从底层开始,层层递进,最后得到最大值。
状态:Nowmax[i][j]:第i排第j个出发所能得到的最大值。
Number[i][j]:第i排第j个表示的数。
状态转移方程:Nowmax[i][j]=max(Nowmax[i+1][j],Nowmax[i+1][j+1])+Number[i][j];
#include<cstdio>
#include<algorithm>//使用max(x,y)函数所需要的头文件
using namespace std;
const int SZ=1005;//定义一个常量SZ表示数组大小
int Nowmax[SZ][SZ],Number[SZ][SZ],Sum;
//Sum表示层数,Nowmax表示从当前点出发所能得到的最大和
//Number表示当前点表示的数
int main()
{
scanf("%d",&Sum);
for(int i=1;i<=Sum;i++)
for(int j=1;j<=i;j++)
scanf("%d",&Number[i][j]);//输入
for(int i=Sum;i>=1;i--)//从底层向上计算
for(int j=1;j<=i;j++)
Nowmax[i][j]=max(Nowmax[i+1][j],Nowmax[i+1][j+1])+Number[i][j];
//转移状态时别忘了加上本身这个数
printf("%d\n",Nowmax[1][1]);//输出
return 0;
}