数字三角形问题(线性DP)

线性DP是动态规划问题中的一类问题,指状态之间有线性关系的动态规划问题。

动态规划的算法思想就是将待求解的问题分解成较小且相同子问题,最终产生整体最优解。

经典问题有数字三角形

 题目意思:
自上而下走,每次只能向左下或者右下,找出计算之和最大值输出。

解析:

自下而上,更改每次的状态——最大值(子问题),求出每个位置的最大值,最终得出第一个位置的最大值。

以例题为例如下图所示:

 左边是数塔,右边是每次更新的最大值的状态,最终在 f[1][1] 位置即是整个数塔的最大值,输出即可。

代码:

#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;

const int N=520;
int w[N][N],f[N][N];
int main()
{
    int n;
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=i;j++)
        {
            cin>>w[i][j];
        }
    }
    
    for(int i=1;i<=n;i++)f[n][i]=w[n][i];
    
    for(int i=n-1;i;i--)
    {
        for(int j=1;j<=i;j++)
        {
            f[i][j]=max(w[i][j]+f[i+1][j],w[i][j]+f[i+1][j+1]);
        }
    }
    
    cout<<f[1][1]<<endl;
    return 0;
}

 求路径的数字三角形问题

 

有一个N层数塔,顶层只有一个结点,每向下一层增加一个结点,最底层有N个结点(下图给出了一个5层数塔)。从顶层出发,每个结点可以选择向左下或者向右下行走,一直走到底层。要求找到一条路径,使得路径上的数值之和最大。例如,下图所示的5层数塔的最大和及其路径为:60=8+15+9+10+18。

输入格式:

输入在N+1进行,首先给出数塔的高度值N。接下来的N行输入数塔各层结点的值,第一行给出顶层结点的一个值,每向下一行增加一个值,每行的值之间用空格间隔。

输出格式:

按照如下格式输出最大值及其路径。
最大值[结点-->结点-->... ... -->结点]

输入样例:

5
8
12 15
4  9  5
8 10 5 13
16 7 18 10 9

输出样例:

60[8-->15-->9-->10-->18]

 代码:

#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;

const int N=520;
int w[N][N],f[N][N];
int main()
{
    int n;
    cin>>n;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=i;j++)
            cin>>w[i][j];
    for(int i=1;i<=n;i++)f[n][i]=w[n][i];
    for(int i=n;i;i--)
    {
        for(int j=1;j<=i;j++)
        {
            f[i][j]=max(w[i][j]+f[i+1][j],w[i][j]+f[i+1][j+1]);
        }
    }
    cout<<f[1][1]<<"["<<w[1][1]<<"-->";
    int j=1;
    for(int i=2;i<=n;i++)
    {
        if(f[i][j]>f[i][j+1])cout<<w[i][j];
        else 
        {
            cout<<w[i][j+1];
            j++;
        }
        
        if(i!=n)cout<<"-->";
    }
    cout<<"]";
}

解析:

前面的跟上面一样,找路径的思路就是从f[1][1]开始,每次寻找他的最大值f[i][j],顺着路径向下即可。但是要注意 j 是否要加1,如果左边不用加,向右下的话需要加1,找到最大值f[i][j],输出w[i][j]即可。

  • 0
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Adellle

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值