【寒假每日一题】数字三角形(个人练习)详细题解+推导证明(第二天)

前言

昨天真是人生中奇葩的一天,结果没有更博客,是我的锅,今天还是写一个寒假每日一题来坚持坚持,不是软广,不是硬广,只是个人练习,题目来自usaco training 1.6,模板题。

另外,最近发现自己的代码规范写的不是太好,比如for循环。

我以前的写法:

for(int i=0;i<n;++i){
	......
}

看到的好的写法:

for (int i = 0; i < n; ++ i )
	......

感觉有必要改进改进代码规范了,华为这两年一直在搞代码可信度,慢慢加油吧。

题目

给定一个如下图所示的数字三角形,从顶部出发,在每一结点可以选择移动至其左下方的结点或移动至其右下方的结点,一直走到底层,要求找出一条路径,使路径上的数字的和最大。

        7
      3   8
    8   1   0
  2   7   4   4
4   5   2   6   5

输入格式

  • 第一行包含整数n,表示数字三角形的层数。
  • 接下来n行,每行包含若干整数,其中第 i 行表示数字三角形第 i 层包含的整数。

输出格式

  • 输出一个整数,表示最大的路径数字和。

数据范围

  • 1 ≤ n ≤ 500 1≤n≤500 1n500
  • − 10000 ≤ 三 角 形 中 的 整 数 ≤ 10000 −10000≤三角形中的整数≤10000 1000010000
输入样例:
5
7
3 8
8 1 0 
2 7 4 4
4 5 2 6 5

输出样例:
30

在这里插入图片描述

详细题解

写法1 O ( n 2 ) O(n^2) O(n2)

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 505;

int n;
int w[N][N], f[N][N];

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

毫无疑问,这是一道经典的dp问题,每一次三角形中的一个数都是由它的两个角标数相连,即左下标和右下标,即无法记忆前面的状态,只能推导后面的状态,这是很难的。所以如果是从下向上的话,容易太多了。。。不过这可能比较难想,所以dp题目需要经验,当然我的经验也不足,所以还需要锤炼。

根据状态表示和状态计算即可完成推导公式:
f [ i ] [ j ] = m a x ( f [ i + 1 ] [ j ] + w [ i ] [ j ] , f [ i + 1 ] [ j + 1 ] + w [ i ] [ j ] ) ; f[i][j] = max(f[i+1][j] + w[i][j], f[i+1][j+1] + w[i][j]); f[i][j]=max(f[i+1][j]+w[i][j],f[i+1][j+1]+w[i][j]);

最后提交,AC😁
在这里插入图片描述

推导证明

本题的推导即为dp问题的推导,按照y总的dp思考法,可以分为几个步骤。

第一个是状态表示:你的集合即数组表示的含义是什么,这个很重要且不能忘记;你的属性即求什么样的结果,一般分为三种(最大值,最小值,个数),这个是目标,同样很重要。
在这里插入图片描述
第二个就是状态计算,即如何划分你的集合,简单来说就是归纳总结(数学),你当前的状态是什么,前一个状态是什么,根据属性完成状态推导。

本题来说,

  • 当前状态即 f [ i ] [ j ] f[i][j] f[i][j]
  • 前一个状态即 f [ i + 1 ] [ j ] f[i+1][j] f[i+1][j] f [ i + 1 ] [ j + 1 ] f[i+1][j+1] f[i+1][j+1](这些不是凭空想象出来的,而是根据给出的三角形进行合理推导的),
  • 属性即最大值,

故可以得出结论,并完成代码的书写。

写法2 O ( n 2 ) O(n^2) O(n2)

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 505;

int n;
int f[N][N];

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

最后提交,AC😁
在这里插入图片描述

推导证明

解法2与解法1的本质是一样的,只是为了简化代码,与算法思想无关。

  • 首先可以合并数组,即去掉w数组;
  • 然后是去除w数组所在位置;
  • 最后合并f数组。

举一反三

可以进行多种dp题目的训练,后续可能会不定时更新。

总结

继续努力,坚持更新,2nd打卡。

在这里插入图片描述

我是管小亮 CSDN认证博客专家 TensorFlow PyTorch 图像处理
纸上得来终觉浅,绝知此事要躬行

包括但不局限于机器学习,深度学习,自然语言处理,计算机视觉,知识图谱,还有Python,C++,TensorFlow,Pytorch,Keras,PaddlePaddle等,不定时分享资源(电子书/项目/工具),学习路线,思考,面经等!!!
已标记关键词 清除标记
相关推荐
<p> <strong><span style="font-size:20px;color:#FF0000;">本课程主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的Java学习者</span></strong> </p> <p> <span style="color:#FF0000;"><strong><span style="font-size:18px;">1. 包含:<span style="color:#FFFF00;background-color:#FF0000;">项目源码、</span><span style="color:#FFFF00;background-color:#FF0000;">项目文档、数据库脚本、软件工具</span>等所有资料</span></strong></span> </p> <p> <span style="color:#FF0000;"><strong><span style="font-size:18px;">2. 手把手的带你从零开始部署运行本套系统</span></strong></span> </p> <p> <span style="color:#FF0000;"><strong><span style="font-size:18px;">3. 该项目附带的源码资料可作为毕设使用</span></strong></span> </p> <p> <span style="color:#FF0000;"><strong><span style="font-size:18px;">4. 提供技术答疑和远程协助指导</span></strong></span><strong><span style="font-size:18px;"></span></strong> </p> <p> <br /> </p> <p> <span style="font-size:18px;"><strong>项目运行截图:</strong></span> </p> <p> <strong><span style="font-size:18px;">1)系统登陆界面</span></strong> </p> <p> <strong><span style="font-size:18px;"><img src="https://img-bss.csdn.net/202002241015433522.png" alt="" /><br /> </span></strong> </p> <p> <strong><span style="font-size:18px;"><strong><span style="font-size:18px;">2)学生模块</span></strong></span></strong> </p> <p> <strong><span style="font-size:18px;"><img src="https://img-bss.csdn.net/202002241015575966.png" alt="" /></span></strong> </p> <p> <strong><span style="font-size:18px;"><strong><span style="font-size:18px;">3)教师模块</span></strong></span></strong> </p> <p> <strong><span style="font-size:18px;"><img src="https://img-bss.csdn.net/202002241016127898.png" alt="" /></span></strong> </p> <p> <strong><span style="font-size:18px;"><strong><span style="font-size:18px;">4)系统管理员</span></strong></span></strong> </p> <p> <strong><span style="font-size:18px;"><img src="https://img-bss.csdn.net/202002241016281177.png" alt="" /></span></strong> </p> <p> <strong><span style="font-size:18px;"><img src="https://img-bss.csdn.net/202002241016369884.png" alt="" /></span></strong> </p> <p> <strong><span style="font-size:18px;"><br /> </span></strong> </p> <p> <strong><span style="font-size:18px;"><strong><span style="font-size:18px;">更多Java毕设项目请关注我的毕设系列课程 <a href="https://edu.csdn.net/lecturer/2104">https://edu.csdn.net/lecturer/2104</a></span></strong></span></strong> </p> <p> <strong><span style="font-size:18px;"><br /> </span></strong> </p>
©️2020 CSDN 皮肤主题: 酷酷鲨 设计师:CSDN官方博客 返回首页