如图所示的数字三角形,从顶部出发,在每一结点可以选择向左走或得向右走,一直走到底层,要求找出一条路径,使路径上的值最大。
输入描述 Input Description
第一行是数塔层数N(1<=N<=100)。
第二行起,按数塔图形,有一个或多个的整数,表示该层节点的值,共有N行。
输出描述 Output Description
输出最大值。
样例输入 Sample Input
5
13
11 8
12 7 26
6 14 15 8
12 7 13 24 11
样例输出 Sample Output
86
思路1:普通递归 用二维数组存放三角形。
a[r][j]:第r行第j列的数字
sum(r,j) :从a[r][j]到底边的各个路径中最大数字之和。 复杂度是O(2^N)
#include<iostream>
#include<algorithm>
#define MAXM 110
int a[MAXM][MAXM];
int n;
using namespace std;
int sum(int i, int j)
{
if(i == n)
return a[i][j];
int x = sum(i+1,j);
int y = sum(i+1,j+1);
return max(x,y) + a[i][j];
}
int main()
{
cin >> n;
for(int i = 1; i <= n; i++){
for(int j = 1; j <= i; j++){
cin >> a[i][j];
}
}
cout << sum(1,1);
}
此方法重复计算的太多导致时间超时
优化, 进行记忆性递归 定义一个二维数组 记录每个坐标到下面的最大值。将该数组全部赋值为0,每一项计算前加一个判断 如果不为0,则直接跳过计算防止时间的重复 时间复杂度O(n*n)
#include<iostream>
#include<algorithm>
#define MAXM 110
int sum[MAXM][MAXM] = {0};
int a[MAXM][MAXM];
int n;
using namespace std;
int Sum(int i, int j)
{
if(sum[i][j] != 0) return sum[i][j];
if(i == n) sum[i][j] = a[i][j];
else{
int x = Sum(i+1,j);
int y = Sum(i+1,j+1);
sum[i][j] = max(x,y) + a[i][j];
}
return sum[i][j];
}
int main()
{
cin >> n;
for(int i = 1; i <= n; i++){
for(int j = 1; j <= i; j++){
cin >> a[i][j];
}
}
cout << Sum(1,1);
}
优化 递归变递推 从最下面一行开始逐一往上进行计算
#include<iostream>
#include<algorithm>
using namespace std;
#define MAXM 110
int main()
{
int a[MAXM][MAXM];
int n, i, j;
cin >> n;
for(i = 1; i <= n; i++)
for(j = 1 ; j <=i; j++){
cin >> a[i][j];
}
for(i = n-1; i > 0; i--){
for(j = 1; j <= i; j++){
a[i][j] = max(a[i+1][j], a[i+1][j+1]) + a[i][j];
}
}
cout << a[1][1];
return 0;
}