动态规划2(数塔问题)

2024-01-10 17:38
文章标签 动态 规划 问题 数塔

本文主要是介绍动态规划2(数塔问题),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

数塔问题是二维情况下动态规划的经典问题,下面以洛谷的一个例题来分析数塔问题以及动态规划:原题链接

题目描述

观察下面的数字金字塔。写一个程序来查找从最高点到底部任意处结束的路径,使路径经过数字的和最大。每一步可以走到左下方的点也可以到达右下方的点。在这里插入图片描述
在上面的样例中,从7→3→8→7→5 的路径最大

输入格式

第一个行一个正整数 rr ,表示行的数目。后面每行为这个数字金字塔特定行包含的整数。

输出格式

单独的一行,包含那个可能得到的最大的和。

样例输入

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

样例输出

30

数据范围

对于100%的数据,1 ≤ r ≤ 1000,所有输入在 [0,100] 范围内。

数塔问题递归写法分析:

  • 可以使用一个二维数组存储数塔,需要注意的是,在本题的数塔里,路径可以选择向左或者向右,但是若将数塔存储在二维数组中,数塔路径的选择只能是向下向右下这两个方向
  • 在二维数组中,当前位置的下方是[i + 1][ j ],右下方是[i +1][j + 1]
  • 本题样例中给出的是5层数塔,可以用dfs(1,1)表示从第1行第1列到第5行的最大路径,而想要找到答案,需要先寻找第2行到第5行的最大路径,即将5层数塔的最长路径转化为了4层数塔的最长路径这个子问题。即max{dfs(2,1),dfs(2,2)} + a[1][1]… … 以此类推
  • 当dfs()函数递归到最后1行(x == n)时,如数塔一共5行,目前正在执行dfs(5,1),则直接返回数塔中的第5行第1列的数字a[5][1]即可,之后递归函数会依次向上继续返回

递归写法代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>using namespace std;const int N = 1010;
int a[N][N];//存储数据
int n;//递归函数中需要设置边界,故将n设为全局变量int dfs(int x,int y)//x表示行,y表示列
{if (x == n) return a[x][y];//递归边界return max(dfs(x + 1,y),dfs(x + 1,y + 1)) + a[x][y];
}int main()
{cin >> n;for (int i = 1;i <= n;i++)//读入数塔:数塔有n行for (int j = 1;j <= i;j++)//每行有n列cin >> a[i][j];cout << dfs(1,1) << endl;//dfs(1,1):从第1行第1列到边界的最大路径return 0;
}

当然,当数据范围很大时,由于递归写法的重叠子问题太多,所以又见到了熟悉的TLE… …话不多说直接上图在这里插入图片描述
下面给出本题的AC代码

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>using namespace std;const int N = 1010;
int a[N][N];//存储数塔
int f[N][N];//表示从第i行第j列到第n行的最大路径
int n;int main()
{while (cin >> n){for (int i = 1;i <= n;i++)for (int j = 1;j <= i;j++)cin >> a[i][j];for (int i = n;i >= 1;i--)//用i来表示行,且从最后一行开始for (int j = 1;j <= i;j++)//每行有i列,且从第一列开始f[i][j] = max(f[i + 1][j],f[i + 1][j + 1]) + a[i][j];//自底向上计算最长路径cout << f[1][1] << endl;//当for循环结束完毕之后f[1][1]:从数塔第1行第1列开始的最长路径}return 0;
}

动态规划的基本思想:将待求解问题分解成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解。我们需要保存已解决的子问题的答案,这样可以避免大量的重复计算,节省时间。我们会用一个表来记录所有已解的子问题的答案。不管该子问题以后是否被用到,只要它被计算过,就将其结果填入表中,而在需要时再找出已求得的答案。

换个新数塔哈~
在这里插入图片描述

如上图所示,若想找到这个8层数塔的最长路径,即将问题描述为:

  • 从第一行第一列的数字7开始,找出一条最长路径。
    很明显,若想解决上面的问题,有两条路径可以选择:
    从数字7下面的0开始寻找路径(子问题)
    从数字7右下的11开始寻找路径(子问题)

以此类推,不难发现,从红色位置开始找出一条最长路径,这个问题依赖于很多个子问题,而这些子问题构成了绿色部分。

我们只需要计算出①②两个子问题的答案,选择其中较大的值,再加上第一行第一列的那个数字,就可以得到数塔的最长路径。

由以上分析,得出状态转移方程

dp[i][j] = max{dp[i + 1][j],dp[i + 1][j + 1]} + a[i][j]
边界:当i > n时,f[i][j] = 0;

下面再给出数塔的一个例题
原题链接

AC代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>using namespace std;const int N = 1010;
int a[N][N];//存储数塔
int f[N][N];//表示从第i行第j列到第n行的最大路径
int n;int main()
{int c;cin >> c;while (c--){cin >> n;for (int i = 1;i <= n;i++)for (int j = 1;j <= i;j++)cin >> a[i][j];for (int i = n;i >= 1;i--)//用i来表示行,且从最后一行开始for (int j = 1;j <= i;j++)//每行有i列,且从第一列开始f[i][j] = max(f[i + 1][j],f[i + 1][j + 1]) + a[i][j];//自底向上计算最长路径cout << f[1][1] << endl;//当for循环结束完毕之后f[1][1]:从数塔第一层开始的最长路径}return 0;
}

这篇关于动态规划2(数塔问题)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/591569

相关文章

Java使用Javassist动态生成HelloWorld类

《Java使用Javassist动态生成HelloWorld类》Javassist是一个非常强大的字节码操作和定义库,它允许开发者在运行时创建新的类或者修改现有的类,本文将简单介绍如何使用Javass... 目录1. Javassist简介2. 环境准备3. 动态生成HelloWorld类3.1 创建CtC

Vue3绑定props默认值问题

《Vue3绑定props默认值问题》使用Vue3的defineProps配合TypeScript的interface定义props类型,并通过withDefaults设置默认值,使组件能安全访问传入的... 目录前言步骤步骤1:使用 defineProps 定义 Props步骤2:设置默认值总结前言使用T

Web服务器-Nginx-高并发问题

《Web服务器-Nginx-高并发问题》Nginx通过事件驱动、I/O多路复用和异步非阻塞技术高效处理高并发,结合动静分离和限流策略,提升性能与稳定性... 目录前言一、架构1. 原生多进程架构2. 事件驱动模型3. IO多路复用4. 异步非阻塞 I/O5. Nginx高并发配置实战二、动静分离1. 职责2

解决升级JDK报错:module java.base does not“opens java.lang.reflect“to unnamed module问题

《解决升级JDK报错:modulejava.basedoesnot“opensjava.lang.reflect“tounnamedmodule问题》SpringBoot启动错误源于Jav... 目录问题描述原因分析解决方案总结问题描述启动sprintboot时报以下错误原因分析编程异js常是由Ja

MySQL 表空却 ibd 文件过大的问题及解决方法

《MySQL表空却ibd文件过大的问题及解决方法》本文给大家介绍MySQL表空却ibd文件过大的问题及解决方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考... 目录一、问题背景:表空却 “吃满” 磁盘的怪事二、问题复现:一步步编程还原异常场景1. 准备测试源表与数据

解决Nginx启动报错Job for nginx.service failed because the control process exited with error code问题

《解决Nginx启动报错Jobfornginx.servicefailedbecausethecontrolprocessexitedwitherrorcode问题》Nginx启... 目录一、报错如下二、解决原因三、解决方式总结一、报错如下Job for nginx.service failed bec

SysMain服务可以关吗? 解决SysMain服务导致的高CPU使用率问题

《SysMain服务可以关吗?解决SysMain服务导致的高CPU使用率问题》SysMain服务是超级预读取,该服务会记录您打开应用程序的模式,并预先将它们加载到内存中以节省时间,但它可能占用大量... 在使用电脑的过程中,CPU使用率居高不下是许多用户都遇到过的问题,其中名为SysMain的服务往往是罪魁

MySQ中出现幻读问题的解决过程

《MySQ中出现幻读问题的解决过程》文章解析MySQLInnoDB通过MVCC与间隙锁机制在可重复读隔离级别下解决幻读,确保事务一致性,同时指出性能影响及乐观锁等替代方案,帮助开发者优化数据库应用... 目录一、幻读的准确定义与核心特征幻读 vs 不可重复读二、mysql隔离级别深度解析各隔离级别的实现差异

C++ vector越界问题的完整解决方案

《C++vector越界问题的完整解决方案》在C++开发中,std::vector作为最常用的动态数组容器,其便捷性与性能优势使其成为处理可变长度数据的首选,然而,数组越界访问始终是威胁程序稳定性的... 目录引言一、vector越界的底层原理与危害1.1 越界访问的本质原因1.2 越界访问的实际危害二、基

Python多线程应用中的卡死问题优化方案指南

《Python多线程应用中的卡死问题优化方案指南》在利用Python语言开发某查询软件时,遇到了点击搜索按钮后软件卡死的问题,本文将简单分析一下出现的原因以及对应的优化方案,希望对大家有所帮助... 目录问题描述优化方案1. 网络请求优化2. 多线程架构优化3. 全局异常处理4. 配置管理优化优化效果1.