数塔问题
给定一个数塔,其存储形式为如下所示的下三角矩阵。在此数塔中,从顶部出发,在每一节点可以选择向下走还是向右走,一直走到底层。请找出一条路径,使路径上的数值和最大。
输入样例(数塔):
9
- 15
10 6 8
2 18 9 5
19 7 10 4 16
输出样例(最大路径和):
59
运行截图
具体算法
- 初始化动态规划表 (dp 数组):
- 创建一个二维数组 dp,其大小为 (n+1) x (n+1),其中 n 是输入的塔的层数。
- dp[i][j] 表示从塔顶到第 i 行、第 j 列的最大路径和。
- 填充动态规划表 (dp 数组):
- 使用嵌套循环遍历动态规划表,从第二行开始(第一行是塔的顶部)。
- 对于每个单元格 dp[i][j],考虑两个来源:来自左上方的路径 (dp[i-1][j-1]) 和来自上方的路径 (dp[i-1][j])。
- 从这两个路径中选择较大的值,加上当前单元格的值 (data[i-1][j-1]),更新 dp[i][j]。
- 具体的更新公式为:dp[i][j] = data[i-1][j-1] + max(dp[i-1][j-1], dp[i-1][j])
- 这样,动态规划表逐渐被填充,直到最后一行,即底部。
- 动态规划表的创建完成。
- 这个过程确保在填充表格时,每个单元格都包含了从塔顶到该单元格的最大路径和。最终,整个动态规划表都被填满,其中 dp[n][i] 中的最大值表示从塔顶到底部的最大路径和。
c++代码实现
#include <iostream>
#include <algorithm>
using namespace std;
int data[50][50];//存储原数据表
int dp[50][50];//存储过程表
int n;//塔的层数
void create(){ //创建过程表
for(int i=1;i<n+1;i++){
for(int j=1;j<i+1;j++){
if(dp[i-1][j]>=dp[i-1][j-1])
dp[i][j]=dp[i-1][j]+data[i-1][j-1];
else
dp[i][j]=dp[i-1][j-1]+data[i-1][j-1];
}
}
}
void bl(){ //遍历过程表
cout<<"**************过程表***********"<<endl;
for(int i=0;i<n+1;i++){
for(int j=0;j<i+1;j++){
cout<<dp[i][j]<<" " ;
}
cout<<endl;
}
}
void find(){ //查询最大路径和
int max=0;
for(int i=0;i<n+1;i++){
if(dp[n][i]>max){
max=dp[n][i];
}
}
cout<<"最大路径和:"<<max<<endl;;
}
void create_y(){
cout<<"输入塔的层数:"<<endl;
cin>>n;
for (int i = 0; i < n; ++i)
{
cout<<"输入第"<<i+1<<"层的数据:"<<endl;
for (int j = 0; j <= i; ++j)
{
cin >> data[i][j];
}
}
}
void bl_y(){
cout<<"*********源数据表*************"<<endl;
for (int i = 0; i < n; ++i)
{
for (int j = 0; j <= i; ++j)
{
cout<< data[i][j]<<" ";
}
cout<<endl;
}
}
int main()
{
create_y();
bl_y();
create();
bl();
find();
}