【问题描述】
给定一个数塔,如下图所示。在此数塔中,从顶部出发,在每一节点可以选择走左下或右下,一直走到底层。请找出一条路径,使路径上的数值和最大。
9 |
||||||||
12 |
15 |
|||||||
10 |
6 |
8 |
||||||
2 |
18 |
9 |
5 |
|||||
19 |
7 |
10 |
4 |
16 |
【输入形式】
输入时第一行一个整数n,表示该数塔的行数,其余n行表示该塔每行的数值
【输出形式】
输出包含两行,第一行为最大路径上的数值之和, 第二行n个数字为从上而下最大路径数值
【样例输入】
5
9
12 15
10 6 8
2 18 9 5
19 7 10 4 16
【样例输出】
59
9 12 10 18 10
#include<bits/stdc++.h>
using namespace std;
int main() {
int n;
cin>>n;
int a[n][n];
int b[n][n];
int increase[n][n];//用来记录路途增量
memset(increase,0,sizeof(increase));//增量全部初始化为0
int key=1;
for(int i=0; i<n; i++) {//按规律进行输入
for(int j=0; j<key; j++) {
cin>>a[i][j];
b[i][j]=a[i][j];
}
key++;
}
//如果直接求最长路径而不求具体路线时,直接动态规划
//a[i][j]表示当走到第i行j列时,所用的最长路径
//思路是:从倒数第二行开始,从下往上讨论
//又因为此时要求具体路径,所以这里用增量(increase)进行路径的标记
for(int i=n-2; i>=0; i--) {
for(int j=0; j<n; j++) {
if(a[i+1][j]<a[i+1][j+1]) { //右下大于左下
increase[i][j]=1;
}
a[i][j]=max(a[i+1][j],a[i+1][j+1])+a[i][j];
}
}
cout<<a[0][0]<<endl;
int j=0;
for(int i=0; i<n; i++) {
cout<<b[i][j]<<' ';
j+=increase[i][j];
}
return 0;
}