任务描述
本关任务:计算数字三角形的最佳路径和。
数字三角形的最佳路径和
有一个数字三角形,从三角形的顶部到底部有很多条不同的路径,路径上的每一步只能从一个数走到下一层上和它最近的左边的数或者右边的数。
对于每条路径,把路径上面的数加起来可以得到一个和,和最大的路径称为最佳路径。请找出最佳路径上的数字之和。
比如对于数字三角形:
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
最佳的路径和是:7 + 3 + 8 + 7 + 5 = 30
。
解题思路
对于这个题,我们也可以用递归方式解决,可以计算出所有的路径和,然后选出其中的最大值,比如:
int arr[10][10];
int height; //三角形的高度
int MaxSum(int n,int k)
{
if(n == height - 1)
{
//三角形的底层直接返回节点值
return arr[n][k];
}
//选择下一层的左边一个节点
int v1 = MaxSum(n + 1,k);
//选择下一层的右边一个节点
int v2 = MaxSum(n + 1,k + 1);
//选择两条路径中和最大的那一条
return max(v1,v2) + arr[n][k];
}
通过观察代码可以得出,计算MaxSum(n, k)
和MaxSum(n, k + 1)
时,都需要计算MaxSum(n + 1, k + 1)
。这就造成了重复计算,影响了计算效率。
因此我们可以在第一次计算完成后记录下MaxSum(n + 1, k + 1)
的结果,在之后的计算中直接使用。
可以设置一个数组maxSum
,maxSum[n][k]
代表以第n
层第k
个节点为根时,最佳路径的和。
由于上层数据依赖下层数据,因此我们采用从底向上的计算顺序。
显然对于三角形的底层,maxSum[height - 1][k]
就等于对应的节点值,即arr[height - 1][k]
。
接下来我们思考如何从n + 1
层maxSum
得到n
层maxSum
。
为了取到最大值,那么n
层的每个节点的值应该选择与相邻的两个n + 1
层节点的值中最大的一个求和,即maxSum[n][k] = max(maxSum[n + 1][k] , maxSum[n + 1][k + 1]) + arr[n][k]
。
而且我们发现,每一层的maxSum
只与下一层的maxSum
有关,那么我们只需要一个一维数组来存储maxSum
即可。
因此得到的大致程序结构如下:
设置maxSum为三角形底层各节点的值
for 遍历层数
{
遍历maxSum,选出相邻两个元素中最大的一个,加上数字三角形中对应位置的节点值。
将求出的值写回到maxSum的适当位置
}
至此程序结构已经大致完成,请你补全代码,完成本关任务。
编程要求
右侧编辑器中有一个函数MaxSum
,它有两个参数arr
和wid
,其中wid <= 10
。
arr
是一个二维数组,有wid
层,第一层(即arr[0]
)有1
个元素,第二层(即arr[1]
)有2
个元素,以此类推。数字三角形每一层的值,是从索引0
开始,连续的存放在每一层对应的数组中的。
请你在这个函数中补充代码,计算并输出这个数字三角形的最佳路径和,占一行。具体见测试说明。
测试说明
平台会对你编写的代码进行测试:
预期输入: 5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
预期输出: 30
每组输入分为多行,第一行是一个整数wid
,下面wid
行为三角形的内容。
#include <iostream>
// 包含输入输出流头文件
#include <algorithm>
// 包含算法头文件,用于使用max函数
using namespace std;
// 使用标准命名空间
void MaxSum(int arr[][10], int wid)
// 定义函数MaxSum,参数为一个二维数组arr和一个整数wid
{
int maxSum[10] = {0};
// 创建一个数组maxSum,用于存储每个节点的最佳路径和,初始值全部为0
// 将底层节点的值写入maxSum数组
for (int i = 0; i < wid; i++)
// 循环,遍历底层节点的索引
{
maxSum[i] = arr[wid - 1][i];
// 将底层节点的值存入maxSum数组中,索引为i
}
// 从倒数第二层开始,向上计算最佳路径和
for (int i = wid - 2; i >= 0; i--)
// 循环,从倒数第二层开始向上计算
{
for (int j = 0; j <= i; j++)
// 循环,遍历当前层的每个节点
{
// 选取相邻两个节点中的最大值,并加上当前节点的值,更新maxSum数组
maxSum[j] = max(maxSum[j], maxSum[j + 1]) + arr[i][j];
}
}
// 输出最佳路径和,即maxSum数组的第一个元素
cout << maxSum[0] << endl;
}