题目描述
观察下面的数字金字塔。
写一个程序来查找从最高点到底部任意处结束的路径,使路径经过数字的和最大。每一步可以走到左下方的点也可以到达右下方的点。
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
在上面的样例中,从7→3→8→7→5 的路径产生了最大
输入格式
第一个行一个正整数 rr ,表示行的数目。
后面每行为这个数字金字塔特定行包含的整数。
输出格式
单独的一行,包含那个可能得到的最大的和。
输入输出样例
输入 #1复制
5 7 3 8 8 1 0 2 7 4 4 4 5 2 6 5
输出 #1复制
30
说明/提示
【数据范围】
对于 100% 的数据,1≤r≤1000,所有输入在 [0,100] 范围内。
题目翻译来自NOCOW。
USACO Training Section 1.5
IOI1994 Day1T1
思路简介
由题可知,a[i][j]点可到a[i+1][j]和a[i+1][j+1]点。所以每个点a[i][j]可由a[i-1][j]和a[i-1][j-1]到来。
因为每一行数据都是已知的,本题可以采用"我为人人”的方法,即利用已知推未知的方法来层层向上推出答案。比如,最底层到达底层的最大数字之和是已知的(即每一位的本身),倒数第二层到达底层的最大数字之和可以通过本层和最后一层推出,即可以通过较低层来推出上一层的最优解答,如此层层递推,一直到顶部,保证每一步子问题都是最优的,这样顶部的解也是最优的。不妨设置maxl[i][j]的值来表示点[i][j]到达底部最大数字之和。所以每次利用maxl[i - 1][j - 1] = a[i - 1][j - 1] + max(maxl[i][j], maxl[i][j - 1]) 和maxl[i - 1][j] = a[i - 1][j] + max(maxl[i][j], maxl[i][j + 1]) ,便实现了通过较低层来推出较高层的答案。最后要求的便是maxl[1][1]
AC代码如下:
#include<bits/stdc++.h>
using namespace std;
#define MAX 1005
int a[MAX][MAX];
int maxl[MAX][MAX];//max1[i][j]的值表示经过此点到底最大的和,题目要求maxl[i][j]
int main() {
int n;
cin >> n;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= i; j++) {
cin >> a[i][j];
maxl[i][j] = a[i][j];
}
}
for (int i = n; i >= 1; i--) {
for (int j = n; j >= 1; j--) {
if (i - 1 >= 1 && i - 1 <= n && j - 1 >= 1 && j - 1 <= n)
maxl[i - 1][j - 1] = a[i - 1][j - 1] + max(maxl[i][j], maxl[i][j - 1]);//和右边的点一起更新其他点
if (i - 1 >= 1 && i - 1 <= n && j - 1 >= 1 && j - 1 <= n)//确保数据在界内
maxl[i - 1][j] = a[i - 1][j] + max(maxl[i][j], maxl[i][j + 1]);//和左边的点一起更新其他点
}
}
cout << maxl[1][1];
return 0;
}
该博客探讨了一种动态规划策略,用于解决寻找数字金字塔中从顶部到底部路径和最大的问题。给出的示例代码展示了如何通过逐层回溯,计算每个位置到达底部的最大和,最终得出整个路径的最大和。这种方法适用于数据范围在一定限制内的问题,保证了找到全局最优解。
772

被折叠的 条评论
为什么被折叠?



