数塔问题的理解

关于自己对数塔问题的理解

题意是怎么走找到最大的数值总和

这里是运用逆行思维


d[x][y]=max (d[x+1][y],d[x+1][y+1])  +a[x][y]

用过一个二维数组d 记住每个点的下一条路的最大总值
然后输出的最终d 就是总值的最大了 
分为子问题解决
最底部往上 一直找最大的相加

for(int i=1;i<=n;i++)
d[n][i]=a[n][i];
第一个for ,让每一个d都有该点的初始值
for(int x=n-1;x>0;x--)
找出所有的x 第一层不算
for(int y=1;y<=x;y++)
找出所有的y,
d[x][y]=max(d[x+1][y],d[x+1][y+1])+a[x][y];
分支之后的2个都比较一次
 

#include <iostream>
#include <algorithm>
 
using namespace std;
 
/************************************************************************/
/* 数塔问题                                                               */
/************************************************************************/
const int N = 50;//为了算法写起来简单,这里定义一个足够大的数用来存储数据(为了避免运算过程中动态申请空间,这样的话算法看起来比较麻烦,这里只是为了算法看起来简单)
int data[N][N];//存储数塔原始数据
int dp[N][N];//存储动态规划过程中的数据
int n;//塔的层数
 
/*动态规划实现数塔求解*/
void tower_walk()
{
    // dp初始化
    for (int i = 0; i < n; ++i)
    {
        dp[n - 1][i] = data[n - 1][i];
    }
    int temp_max;
    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];
        }
    }
}
 
/*打印最终结果*/
void print_result()
{
    cout << "最大路径和:" << dp[0][0] << '\n';
    int node_value;
    // 首先输出塔顶元素
    cout << "最大路径:" << data[0][0];
    int j = 0;
    for (int i = 1; i < n; ++i)
    {
        node_value = dp[i - 1][j] - data[i - 1][j];
        /* 如果node_value == dp[i][j]则说明下一步应该是data[i][j];如果node_value == dp[i][j + 1]则说明下一步应该是data[i][j + 1]*/
        if (node_value == dp[i][j + 1]) ++j;
        cout << "->" << data[i][j];
    }
    cout << endl;
}
 
int main()
{
    cout << "输入塔的层数:";
    cin >> n;
    cout << "输入塔的节点数据(第i层有i个节点):\n";
    for (int i = 0; i < n; ++i)
    {
        for (int j = 0; j <= i; ++j)
        {
            cin >> data[i][j];
        }
    }
 
    tower_walk();
    print_result();
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值