信息学奥赛第十九节 —— 动态规划初步-程序员宅基地

技术标签: 算法  信息学奥赛  动态规划  

概念

多阶段决策问题:对于某一类活动,可以分为若干个相互联系的阶段,每个阶段都需要做出决策,采取一定的措施,这个阶段的决策确定之后,会影响到下一个阶段。每一个阶段的决策构成了一个决策序列,称为策略。每个阶段都有几个决策可以选择,从而就有很多个策略可以选择,在所有可以选择的策略中选取一个最优的策略,可以达到我们预定的效果。动态规划就是解决多阶段决策问题最优的通用方法。
在这里插入图片描述

利用最短路径问题理解多阶段决策

在这里插入图片描述

在上图中,如果想求A到E的最短路径,在这个过程中,涉及了A——>B、B——>C、C——>D、D——>E这几个阶段,在每个阶段中,又有多种决策(权值不同),前一个决策的结果会影响后面的决策,但是后面的决策不会反过来影响前面的决策。
下面是多种不同的策略,使用一定的方法从其中选择出最优的策略,计算出A、E之间的最短路径,就是动态规划算法可以解决的事情。

  • A——>B1——>C1——>D1——>E
  • A——>B1——>C2——>D1——>E
  • A——>B2——>C3——>D2——>E
  • A——>B2——>C3——>D3——>E
  • … …
数塔问题(原题链接)

题目描述

有如下所示的数塔,要求从底层走到顶层,若每一步只能走到相邻的结点,则经过的结点的数字之和最大是多少?
在这里插入图片描述

输入

输入数据首先包括一个整数N(1 <= N <= 100),表示数塔的高度,接下来用N行数字表示数塔,其中第i行有个i个整数,且所有的整数均在区间[0,99]内。

输出

从底层走到顶层经过的数字的最大和是多少?

样例输入

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

样例输出

30

解题思路:数塔一共有5层,顶层为第一层,底层为第五层。若想从第五层走到第一层,经过的数字之和最大,需要保证在到达第二层的时候,经过的数字之和最大。即如果需要在某个点使得数字之和最大,那么需要在到达这个点之前使得数字之和最大,最后加上这个点的数字即可。
在这里插入图片描述

同理,若想在到达第二层的时候经过的数字之和最大,那么需要在到达第三层的时候,经过的数字之和最大… …以此类推。通过分析可以得到,当前点只可以由其正下方和右下方的点到达,设dp[i][i]表示走到第i行第j列的时候,经过的数字之和的最大值,那么可以得到状态转移方程

dp[i][j] = max(dp[i + 1][j],dp[i + 1][j + 1]) + a[i][j]

最后,dp[1][1]表示从第五层走到第一层,所经过的数字之和的最大值。
AC代码1 —— 动态规划

#include <iostream>

using namespace std;
const int N = 110;
int dp[N][N],a[N][N],n;

int main()
{
    
    scanf("%d",&n);
    for (int i = 1; i <= n;i++)
        for (int j = 1;j <= i;j++)
            scanf("%d",&a[i][j]);//读入数据
            
    //初始化dp数组,最后一层不需要状态转移
    for (int i = 1;i <= n;i++) dp[n][i] = a[n][i];
    
    //从倒数第二层开始状态转移
    for (int i = n - 1;i >= 1;i--)//枚举行
        for (int j = 1;j <= n;j++)//枚举列
            dp[i][j] = max(dp[i + 1][j],dp[i + 1][j + 1]) + a[i][j];//状态转移方程
    cout << dp[1][1] << endl;
    return 0;
}

参考代码2 —— DFS:尝试深度优先搜索,直接暴力搜索所有路径,记录最大值即可。另外,本题的本质是寻找一条路径,使得这条路径上的数字之和最大,故不管是从顶到底,还是从底到顶,最终的结果应该是一样的。根据以上分析,可以从a[1][1]开始搜索最大和。

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

using namespace std;
const int N = 110;
int a[N][N],n;
int maxn,sum;//maxn存储最后的结果

int dfs(int x,int y,int sum)
{
    
    //dfs函数中第三个参数用来更新最大值
    maxn = max(maxn,sum);
    if (x + 1 <= n)//不能超过边界
    {
    
        dfs(x + 1,y,sum + a[x + 1][y]);//搜索正下方
        dfs(x + 1,y + 1,sum + a[x + 1][y + 1]);//搜索右下方
    }
}

int main()
{
    
    scanf("%d",&n);
    for (int i = 1; i <= n;i++)
        for (int j = 1;j <= i;j++)
            scanf("%d",&a[i][j]);//读入数据
            
    dfs(1,1,a[1][1]);//从第一行第一列开始搜索,初始最大值为a[1][1]
    
    cout << maxn << endl;
    return 0;
}
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/smallrain6/article/details/124924716

智能推荐

Pixhawk原生固件PX4之日期时间的确定_px4日志日期未知-程序员宅基地

文章浏览阅读2.5k次。19701.1 00:00:00年到2000.1.1 00:00:00有多少秒?软件中哪里给的默认时间2000年的?_px4日志日期未知

Ogre射线精确查询_ogre射线准确求交-程序员宅基地

文章浏览阅读736次。bool PickEntity(Ogre::RaySceneQuery* mRaySceneQuery, Ogre::Ray &ray, Ogre::Entity **result, Ogre::uint32 mask ,Ogre::Vector3 &hitpoint, bool excludeInVisible,const Ogre::String& excludeobject, Ogre::R_ogre射线准确求交

/usr/lib/x86_64-linux-gnu/libopencv_highgui.so:对‘TIFFReadRGBAStrip@LIBTIFF_4.0’未定义的引用...-程序员宅基地

文章浏览阅读489次。LIBRARIES+=boost_threadstdc++boost_regexhttps://github.com/rbgirshick/fast-rcnn/issues/52转载于:https://www.cnblogs.com/huhuai/p/10624740.html_/usr/lib/x86_64-linux-gnu/libopencv_highgui.so: undefined reference to `tiff

人大金仓数据库KingbaseES dbms_xmlquery包使用技巧--集合元素处理方式_数据库中的xml数据怎么改-程序员宅基地

文章浏览阅读842次,点赞22次,收藏19次。在目前的KingbaseES的使用过程中,我们会遇到数据库需要存储XML格式的数据,或者需要对查询的数据进行转换的问题,XML格式的数据类似于HTML格式数据,XML是一种扩展标记语言,最早于1998年被引入软件工业界,它不仅可以在WEB前端使用还可以应用于后端数据处理以及数据库存储等。_数据库中的xml数据怎么改

rtc-sfu_rtc sfu-程序员宅基地

文章浏览阅读581次。SFU 的全称是:Selective Forwarding Unit,是一种通过服务器来路由和转发 WebRTC 客户端音视频数据流的方法。如图所示,SFU 服务器最核心的特点是把自己 “伪装” 成了一个 WebRTC 的 Peer 客户端,WebRTC 的其他客户端其实并不知道自己通过 P2P 连接过去的是一台真实的客户端还是一台服务器,我们通常把这种连接称之为 P2S,即:Peer to Server。_rtc sfu

粒子群算法matlab代码(注释很详细哦,图像也美美哒,任意维度)_多种群并行粒子群算法matlab-程序员宅基地

文章浏览阅读4w次,点赞564次,收藏1.1k次。整个程序分为5个脚本pso1_mian.m:主程序,在此脚本内设置参数。pso1_im.m:画出函数图像(仅1维和2维)pso1_in.m:初始化pso1_in2.m:迭代寻优并输出结果另外还有一个目标函数,单独为一个脚本。推荐的测试函数—>这里先上运行结果图下面是源码1.pso1_mian.m这里的目标函数用函数句柄的形式调用(第15行)%% 粒子群算法%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% pso1_im_多种群并行粒子群算法matlab

随便推点

linux中crontab定时执行脚本_cron 每周日凌晨6点执行-程序员宅基地

文章浏览阅读6.4k次。阅读目录1. cron服务【Ubuntu环境】 2. crontab用法 3. 编辑crontab文件 4. 流程举例 5. 几个例子Linux中,周期执行的任务一般由cron这个守护进程来处理。cron读取一个或多个配置文件,这些配置文件中包含了命令行及其调用时间。cron的配置文件称为“crontab”,是“cron table”的简写。回到顶部1. cron服务【Ubu..._cron 每周日凌晨6点执行

时间序列入门学习-02 常用统计学概念及公式-程序员宅基地

文章浏览阅读77次。学习过程中涉及很多统计学公式,然而过去快10年,忘得一干二净,借此文复习一下叭~

CAD异常eNotOpenForWrite-程序员宅基地

文章浏览阅读6.6k次,点赞2次,收藏2次。之前在实际工程中查一个软件崩溃的问题,具体调试到的位置是AcDbDatabase::saveAs函数,应该是将数据库保存回CAD图纸时触发了CAD的"eNotOpenForWrite"报错随后软件崩溃。根据以往的使用情况来看,saveAs函数一般不会导致CAD的报错,且在具体测试后,确定只有该工程中一张特定图纸打开时,调用功能会导致异常发生。其他图纸操作一切正常,包括在打开其他图纸的情况下,对该特_enotopenforwrite

Android10系统中dialog.isShowing返回false问题-程序员宅基地

文章浏览阅读1.6k次。问题现象: 伪代码 使用流程 AcrtivityA– > DialogFragment– > ActivityB– > back to ActivityA { if ( getDialog().isShowing() ){ DialogFragment.dismiss()} } 发现Android9系统环境下 BaseJDDialogFragment调用getDialog().isShowing,返回为true,而Android10系..._android10系统中dialog.isshowing返回false问题

Snipaste 截图工具快捷键大全_snipaste截图快捷键-程序员宅基地

文章浏览阅读1.5k次。下载地址 f1 截图 c 复制_snipaste截图快捷键

敏感目录收集工具_cracer安全工具包密码-程序员宅基地

文章浏览阅读759次。敏感目录收集mysql管理接口后台目录上传目录phpinforobots.txt---->列出防爬行目录安装包安装页面---->index.php爬行Cracer渗透工具包6.0下载链接:https://pan.baidu.com/s/1ac-t-EMrl89aGJMm3pYS5w 密码:a8f11.御剑后台目录扫描    御剑是一款好用的网站后台扫描工具,图..._cracer安全工具包密码