问题描述
从数塔的顶层出发,寻找一条从顶部到底边的路径,使得路径上所经过的数字之和最大。路径上的每一步都只能往左下或右下走。只需要求出这个最大和即可,不必给出具体路径。
三角形的行数为1-100,数字为0-99。
样例输入:
5
8
12 15
3 9 6
8 10 5 12
16 4 18 10 9
样例输出:
60
这是一个基础的DP问题,要想知道第一个结点往下走的时候是往左走还是往右走,就要判断是从左结点走经过的结点数字总数较大还是往右结点走经过的结点数字总数较大,而对于左结点,是往左结点走经过的结点数字总数较大还是往右结点走经过的结点数字总数较大,对于左结点的左结点…你懂的,这个时候就开始循环了。
就这样一直循环到倒数第二层,对于这个结点,是往左节点走好还是往右节点走好,那好办啊,直接比较这个结点的左孩子大还是又孩子大不就结了,把大的孩子数字直接加到这个节点上就得到经过这个结点的最大结点数字总数了,哈哈,这样就好办了,我们就可以逐层求上面的各个节点的最大结点总数了,一直到第一层A[1][1]的值就是经过的结点的数字之和最大是多少。
存储这个数塔我们使用二位数组,而对于任意一个结点,左孩子是dp[i+1][j]或者dp[i+1][j+1],这是我们就要判断它的经过它左孩子得到的最大结点数更大还是右孩子经过的最大结点数更大一点。必须从倒数第二层到第一层逐层判断,这样才能保证孩子中存储的是经过它的最大结点数总数,而不是它自己的结点数。
数组的一层更新完这层存储的数字就是经过该结点的最大结点总数。
点击查看代码
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
#define ll long long
#define Elaina 0
const int N=10050;
ll m,n,f[N][N];
int main(){
cin>>m;
while(m--){
cin>>n;
for(int i=1;i<=n;i++){
for(int j=1;j<=i;j++){
cin>>f[i][j];
}
}
for(int i=n-1;i>0;i--){
for(int j=1;j<=i;j++){
f[i][j]+=max(f[i+1][j],f[i+1][j+1]);
}
}
cout<<f[1][1]<<endl;
}
return Elaina;
}