题目描述
观察下面的数字金字塔。
写一个程序来查找从最高点到底部任意处结束的路径,使路径经过数字的和最大。每一步可以走到左下方的点也可以到达右下方的点。
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
在上面的样例中,从7 到 3 到 8 到 7 到 5 的路径产生了最大
输入输出格式
输入格式:
第一个行包含 R(1<= R<=1000) ,表示行的数目。
后面每行为这个数字金字塔特定行包含的整数。
所有的被供应的整数是非负的且不大于100。
输出格式:
单独的一行,包含那个可能得到的最大的和。
输入输出样例
输入样例#1: 复制
5 7 3 8 8 1 0 2 7 4 4 4 5 2 6 5
输出样例#1: 复制
30
说明
题目翻译来自NOCOW。
USACO Training Section 1.5
算法就不说啦,动态规划,不过一定要用记忆型递归的动态规划
下面是代码
#include<iostream>
#include<math.h>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long int LL;
int r;
const int N = 1001;
int stor[N][N];//用来存储读取到的数值
LL result[N][N];//用来记录每个坐标处的求得的最大值,避免重复计算
int solve(int x, int y) {
if (x == r) {//如果读取到最后一行,直接返回结果,并将结果存储起来
result[x][y] = stor[x][y];
return stor[x][y];
}
else {
int qian,hou;
if (result[x + 1][y] != -1) {/*用来判断下一行的前一个数是否计算过
如果计算过,就直接拿来用,否则递归,并存储*/
qian= result[x+1][y];
}
else {
qian=solve(x+1, y);
result[x+1][y] = qian;
}
if (result[x+1][y + 1] != -1) {//同理
hou = result[x+1][y + 1];
}
else {
hou = solve(x+1, y + 1);
result[x+1][y + 1] = hou;
}
result[x][y] = max(qian, hou) + stor[x][y];//状态转移方程
}
}
int main()
{
cin >> r;
for(int i=1;i<=r;i++)
for (int j = 1; j <= i; j++) {
cin >> stor[i][j];
result[i][j] = -1;//将数组初始化为-1,不能为零,因为读取到的数值可能也为0
}
solve(1, 1);
cout << result[1][1] << endl;
return 0;
}