题目要求
给定一个数塔,其存储形式为如下所示的下三角矩阵。在此数塔中,从顶部出发,在每一节点可以选择向下走还是向右走,一直走到底层。请找出一条路径,使路径上的数值和最大。
输入样例(数塔):
9
12 15
10 6 8
2 18 9 5
19 7 10 4 16
输出样例(最大路径和):
59
题目分析
用一句话解释动态规划就是 “记住你之前做过的事”,如果更准确些,其实是 “记住你之前得到的答案”。
对于该题目,我们可以自上到下分析,自下到上计算
就是说你从上面一直选最大的,使用贪心算法,是不对。因为我们不知道在某个节点的下一个节点更大或者更小。
所以我们可以从下往上找出一条最大路径,不停的更新最大值,直到第二层,我们就选择出了一天最大路径
以题目为例:
第五层的数据分别是 19 7 10 4 16
从第四层开始 : 如果选择了2,在第五层的(19 ,7),必然要选择19
那么路径最大只能是 2—>19= 21;
如果选择了18,在第五层的(7,10),必然要选择10
那么路径最大只能是 18—>10= 28;
如果选择了9,在第五层的(10 ,4),必然要选择10
那么路径最大只能是 9—>10= 19;
如果选择了5,在第五层的(4 ,16),必然要选择16
那么路径最大只能是 5—>16= 21;
第三层 : 如果选择了10,在第四层的(2 ,18),必然要选择18(28>21)
那么路径最大只能是 10—>18—>10= 38;
如果选择了6,在第四层的(18,9),必然要选择18(28>19)
那么路径最大只能是 6—>18—>10= 34;
如果选择了8,在第四层的(9 ,5),必然要选择5(21>19)
那么路径最大只能是 8—> 5—>16= 29;
........
以此类推,直到第二层,就知道从第一层该怎么选,加上第二层的最大路径,就是题目要求的最大路径。
用表格表示:
59 | ||||
50 | 49 | |||
38 | 34 | 29 | ||
21 | 28 | 19 | 21 | |
19 | 7 | 10 | 4 | 16 |
代码实现解析
#include <iostream>
#include <algorithm>
using namespace std;
int data[50][50];//存储原始数据
int dp[50][50];//存储动态规划过程中的数据
int n;//塔的层数
void ShuT()
{
//先将数塔最底层数据放入动态规划dp数组第五层
for (int i = 0; i < n; ++i)
{
dp[n - 1][i] = data[n - 1][i];
}
//临时存放向下向右两个值的,最大那个
int temp_max;
//开始往dp数组中存放每个小阶段的路径值
for (int i = n - 1; i >= 0; --i) //层数,从下往上进行
{
for (int j = 0; j <= i; ++j) //不同层数值的位置
{
// 使用递推公式计算dp的值
temp_max = max(dp[i + 1][j], dp[i + 1][j + 1]); //取向下,向右的最大值
dp[i][j] = temp_max + data[i][j]; //dp数组存放当前路径的最大值
}
}
}
int main()
{
cin>>n;
for (int i = 0; i < n; ++i)
{
for (int j = 0; j <= i; ++j)
{
cin >> data[i][j];
}
}
ShuT();
cout << "最大路径和:" << dp[0][0] <<endl;
}
若有不足之处,希望大家多多提出建议,共同进步!!!