动态规划专题一(动态规划的基本模型)

news2024/9/30 1:28:09

先上例题1

1258:【例9.2】数字金字塔

信息学奥赛一本通(C++版)在线评测系统 (ssoier.cn)

1258:【例9.2】数字金字塔


时间限制: 1000 ms         内存限制: 65536 KB
提交数: 36341     通过数: 21547

【题目描述】

观察下面的数字金字塔。写一个程序查找从最高点到底部任意处结束的路径,使路径经过数字的和最大。每一步可以从当前点走到左下方的点也可以到达右下方的点。

在上面的样例中,从1313到88到2626到1515到2424的路径产生了最大的和8686。

【输入】

第一个行包含R(1≤R≤1000)�(1≤�≤1000),表示行的数目。

后面每行为这个数字金字塔特定行包含的整数。

所有的被供应的整数是非负的且不大于100100。

【输出】

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

【输入样例】

5
13
11 8
12 7  26
6  14 15 8
12 7  13 24 11

【输出样例】

86

题目要求从顶点出发到尾端找到一条路径使得改路径权重和最大  

一:暴搜

显然对于这个数字金字塔我们可以直接使用暴搜遍历所有的路径可能,通过比较得到最大值

这时对于不同的输入n,我们每一次搜的次数将爆炸形增长。

分析其中原因:对于同一个点会经过多次计算,而每一次选择都有俩个,我们以答案视角出发,对于图中n个点,它的最优路径都是唯一固定的,也就是我们在枚举路径时,其实有很多次搜索都是无效的,因为只要我们找到一次了改点的最优路径,后面的搜索都是无用功。

二:记忆化搜索

分析完一

在一的基础优化,设置一个数组用于存放n号结点最优路径的权重,一旦数组中记录了其最优解就不再进行搜索.这就是记忆化搜索

三:动态规划

再分析一下二,其实也会有一些无用功,例如既然已经知道了改路径最优解,但每一次搜索还是会搜索到这个点,只不过改点往下不再搜索了。并且搜索完之后我们也要最各项结果遍历得到最大项

有没有更简单快捷的方式?

换一个思路 ==> 从下往上搜索

简单思考一下,对于上层结点路径的最优解取决于其下层结点的权重

对于每一层结点只有俩个选择,其中最后一层没有选择,那我们不妨从n - 1层开始对每一个结点的选择进行枚举,每一次都选择最大项,层层向上传递答案,此时我们数组的含义就是经过MAP[i][j]结点路径最优解的权重,最后我们的MAP[0][0]就是整个数字金字塔从最上层到底层最优解的权重。

这就是动态规划的基础思想,根据已有规则,推出一个方法(或者是DP公式)帮助我们找到问题的答案

#include<bits/stdc++.h>
#define endl '\n'
using namespace std;
int n, m;
void slove()
{
    cin >> n;
    vector<vector<int>>MAP(n);
    for(int i = 0;i < n; i++)
        for(int j = 0;j < i + 1;j++)
        {
            cin >> m;
            MAP[i].emplace_back(m);
        }
    //核心代码
    for(int i = n - 2;i >= 0;i--)
        for(int j = 0; j < MAP[i].size();j++)
            MAP[i][j] += max(MAP[i + 1][j],MAP[i + 1][j + 1]);
    cout << MAP[0][0] << endl;
}
int main()
{
    cin.tie(0) -> sync_with_stdio(false);
        slove();
    return 0;
}

这里的DP公式就是 MAP[i][j] += max(MAP[i + 1][j],MAP[i + 1][j + 1]);

1259:【例9.3】求最长不下降序列

【题目描述】

例如13,7,9,16,38,24,37,18,44,19,21,22,63,15。例中13,16,18,19,21,22,63就是一个长度为77的不下降序列,同时也有7 ,9,16,18,19,21,22,63组成的长度为88的不下降序列。

【输入样例】

14
13 7 9 16 38 24 37 18 44 19 21 22 63 15

【输出样例】

max=8
7 9 16 18 19 21 22 63

这题如果是连续的子序列很明显一个简单的滑动窗口就可以轻松解决了,那么面对这种情况又该怎么办呢?

定义DP数组状态:对于任意DP[i]表示以i号元素作为结尾的不下降序列大小

首先还是先分析子序列的关系

对任意 1 <=  i   <   j <= n 

若满足num[j]  >= num[i] == >> 说明以num[j]结尾的子序列长度是在num[i] 的基础上新填num[j]元素不难理解 例: 1 2 3 ==>> 以1结尾的子序列长度为1 , 2满足>= 1的条件,将2纳入序列中间,此时以2结尾的最长子序列为2

对于DP数组转移表达式为DP[j] = DP[i] + 1;

尤其要注意的是实际数据的元素并非有序的,因此对于同一个数在不同位置能得到的子序列长度也是不同的,并且元素排序也是杂乱无章的,因此对于所有满足num[j] >= num[i]的条件不能简单的直接转移而是在所有元素中选择最优解 == >> 即 DP[j]  = max(DP[j],DP[i] + 1);

#include<bits/stdc++.h>
#define endl '\n'
using namespace std;
int n, m, ans;
void mycout(vector<int> pre,vector<int> num,int x)
{
    if(!pre[x]){cout<<num[x];return;}
    mycout(pre,num,pre[x]);
    cout << " " << num[x];
}
void slove()
{
    cin >> n;
    vector<int>num(n + 1),DP(n + 1,1),pre(n + 1,0);
    for(int i = 1;i <= n;i++)
        cin >> num[i];
    for(int i = 1;i <= n;i++)
    {//枚举n个结尾
        for(int j = 1; j < i;j++)
        {
            if(num[i] >= num[j] && DP[i] < DP[j] + 1)
            {//保证不下降的前提,为了确保前端数组的准确性将DP[i] = max(DP[i],DP[j] + 1)取最大的条件放到if语句进行维护
                DP[i] = DP[j] + 1;
                pre[i] = j;
            }
            ans < DP[i] ? ans = DP[i], m = i : ans = ans;
        }
    }
    cout << "max=" << ans << endl;
    mycout(pre,num,m);
}
int main()
{
    cin.tie(0) -> sync_with_stdio(false);
        slove();
    return 0;
}

1260:【例9.4】拦截导弹(Noip1999)

O(N ^ 2)做法 + 优化

#include<bits/stdc++.h>
#define endl '\n'
using namespace std;
const int maxn = 1010;
int n, m, ans,res;
void slove()
{
    vector<int>num;
    while(cin >> m)num.emplace_back(m);
    vector<int>DP(num.size() + 1,1),is(num.size(),0);
    for(int i = 0;i < num.size();i++)
    {//枚举n个结尾
        for(int j = 0; j < i;j++)
        {
            if(num[i] <= num[j])
            DP[i] = max(DP[i],DP[j] + 1);
        }
       ans = max(ans,DP[i]);
    }
    int ok = 0;//已拦截导弹数
    int head = 0;//第1个未被拦截的导弹编号
    while(ok < num.size())
    {
        int i = head;
        int H = INT_MAX;//当前可拦截的最大高度
        for(int j = head; j < num.size();j++)
        {
            if(num[j] <= H && is[j] == 0)
            {
                is[j] = true;
                H = num[j];
                ok++;
            }
            else if(head == i && is[j] == 0)head = j;
        }
        res++;
    }
    cout << ans << endl << res;
}

int main()
{
    cin.tie(0) -> sync_with_stdio(false);
        slove();
    return 0;
}

O(nlogn)解法( 非动态规划)

#include<bits/stdc++.h>
#define endl '\n'
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
using namespace std;
int n,m,k,A,B,N,M,K,res,ok;
const int maxn = 1e6 + 10;
bool cmp(int a,int b)
{
    return a >= b;
}
void sove()
{
    vector<int> num,D;
    while(cin >> m)num.emplace_back(m);
    D.emplace_back(num[0]);
    for(int i = 1;i < num.size();i++)
    {
        if(num[i] <= D.back())
           D.emplace_back(num[i]);
        else 
        {
            int T = lower_bound(D.begin() ,D.end() ,num[i] , cmp) - D.begin();
            D[T] = num[i];
        }
    }
    
    vector<bool>is(num.size());
    int head = 0;
    while(ok < num.size())
    {
        int i = head;
        int H = INT_MAX;//当前可拦截的最大高度
        for(int j = head; j < num.size();j++)
        {
            if(num[j] <= H && is[j] == 0)
            {
                is[j] = true;
                H = num[j];
                ok++;
            }
            else if(head == i && is[j] == 0)head = j;
        }
        res++;
    }
    cout << D.size() << endl << res;
}

int main()
{
    cin.tie(0) -> sync_with_stdio(false);
    sove();
    return 0;
}

O(nlogn)解法( 非动态规划)优化

#include<bits/stdc++.h>
#define endl '\n'
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
using namespace std;
int n, m, k, A, B, N, M, K, res, ok;
const int maxn = 1e6 + 10;
bool cmp(int a, int b)
{
    return a >= b;
}
void sove()
{
    vector<int> num, D;
    while (cin >> m)num.emplace_back(m);
    D.emplace_back(num[0]);
    for (int i = 1; i < num.size(); i++)
    {
        if (num[i] <= D.back())
            D.emplace_back(num[i]);
        else
        {
            int T = lower_bound(D.begin(), D.end(), num[i], cmp) - D.begin();
            D[T] = num[i];
        }
    }
    cout << D.size() << endl;
    D.clear();
    D.emplace_back(num[0]);
    for (int i = 1; i < num.size(); i++)
    {
        if (num[i] > D.back())
            D.emplace_back(num[i]);
        else
        {
            int T = lower_bound(D.begin(), D.end(), num[i]) - D.begin();
            D[T] = num[i];
        }
    }
    cout << D.size() << endl;
}

int main()
{
    cin.tie(0)->sync_with_stdio(false);
    sove();
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/585900.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

HotSpot虚拟机OutOfMemoryError异常

目录 一、JVM内存区域 二、堆中对象 1. 对象的创建 2. 对象的内存布局 3. 对象的访问定位 三、OOM异常 1. 堆OOM异常测试 2. 栈SOF异常测试 1)&#xff1a;栈容量过小 2)&#xff1a;大量本地变量 3. 常量池OOM异常测试 4. 方法区测试 5. 堆外内存测试 四、参考资料…

详解FreeRTOS:嵌入式多任务系统的任务互斥和优先级反转(理论篇—9)

在嵌入式多任务系统中,有些资源必须是独占使用的,多个任务对这样的资源的并发访问将导致错误的发生。一般来说,对需要独占使用的资源必须使用互斥方法将对其的并发访问串行化。 在优先级多任务系统中引入互斥方案,会导致任务优先级反转的问题:假如某时低优先级的任务占有…

Zabbix之2023 Zabbix6.4最新高级特性、优缺点及其实现原理总结

目录 Zabbix高级特性1. 自动发现 Zabbix高级特性2. 分布式监控 Zabbix高级特性3. 高级报警 Zabbix高级特性4. 可视化 Zabbix高级特性5. API Zabbix高级特性6. 高可用性 Zabbix高级特性7. 安全性 Zabbix高级特性8. 无代理监控 SNMP IPMI JMX Zabbix高级特性9. Agent…

【Windows】局域网内远程桌面控制

【Windows】局域网内远程桌面控制 1、背景2、设置登录密码3、启用远程桌面4、远程示例 1、背景 工作中的很多场景需要远程操作&#xff0c;这时候可以借助远程桌面应用程序实现&#xff0c; 比如AnyDesk、向日葵、TeamViewer等。 windows10系统&#xff0c;其操作系统自带了远…

python基础知识(三):比较运算符、布尔运算符和位运算

目录 1. 比较运算符2. 布尔运算符3. 位运算 1. 比较运算符 比较运算符通常为以下6种&#xff1a; (1) 大于">“&#xff0c;比较两个数a、b的大小&#xff0c;比较的结果如果a大于b则为True&#xff0c;否则为False&#xff1b; (2) 大于等于”>“&#xff0c;比较…

【论文阅读笔记】Contrast image correction method

论文小结&#xff1a; 本文是2010年发表出来的一篇文章&#xff0c;提出的方法是一种增强对比度的方法&#xff0c;其基本原理是自适应参数的 ganma 校正。ganma 校正的目标在于同时校正曝光过度和曝光不足区域的图像。   同时&#xff0c;为了防止光晕伪影&#xff0c;使用双…

vue 【git】

文章目录 前言一、git 工作流程二、常用的git命令1.git 初始化2.修改的内容提交到暂存区3.暂存区的内容提交到本地仓库4.创建分支5.切换分支6.展示分支7.删除分支8.合并指定分支到当前分支9.本地仓库的内容提交到远程仓库10.合并分支11.上传本地仓库分支到远程仓库分支 前言 什…

路径规划算法:基于闪电搜索优化的路径规划算法- 附代码

路径规划算法&#xff1a;基于闪电搜索优化的路径规划算法- 附代码 文章目录 路径规划算法&#xff1a;基于闪电搜索优化的路径规划算法- 附代码1.算法原理1.1 环境设定1.2 约束条件1.3 适应度函数 2.算法结果3.MATLAB代码4.参考文献 摘要&#xff1a;本文主要介绍利用智能优化…

第12届蓝桥杯Scratch国赛真题集锦

程题 第 1 题 问答题 博土江出题 题目说明 编程实现:博土汪出了5道加法选择题&#xff0c;请同学们给出正确选项 具体要求 1).博士汪问:“n m ?”&#xff0c;n (0-9随机数)&#xff0c;m (0-9随机数) 2).下方A、B、C、D四个选项&#xff0c;随机一个选项为正确答案&#xff…

通过Python的PyPDF2库合并多个pdf文件

文章目录 前言一、PyPDF2库是什么&#xff1f;二、安装PyPDF2库三、查看PyPDF2库版本四、合并多个pdf文件1.引入库2.定义pdf路径3.获取所有要合并的PDF文件名4.创建一个新的PDF文件5.遍历所有PDF文件名6.打开PDF文件7.创建PDF阅读器对象8.遍历PDF中的每一页&#xff0c;并将它们…

嵌入式c语言-进制转换

10进制转2进制 以10进制的16,18为例子 利用短除法 每次除以2并且记录余数 直到商为1 然后从下往上写出 商余数 10进制转16进制 以55 180 500举例 利用短除法 每次除以16并且记录余数 直到商为1 然后从下往上写出 商余数 商和余数要写成16进制的形式 10进制转8进制 以15为…

(浙大陈越版)数据结构 第三章 树(上) 3.3 二叉树的遍历

目录 3.3.1 遍历&#xff08;先中后&#xff09; 二叉树的遍历 先序遍历&#xff1a; 中序遍历 后序遍历 tips: 3.3.2 中序非递归遍历 非递归算法实现的基本思路&#xff1a;使用堆栈 中序遍历的非递归算法具体实现方法为&#xff1a; 3.3.3 层序遍历 难点 解决方法…

经典神经网络(5)GoogLeNet及其在Fashion-MNIST数据集上的应用

经典神经网络(5)GoogLeNet及其在Fashion-MNIST数据集上的应用 1 Inception V1 的简述 Inception 网络是卷积神经网络的一个重要里程碑。在Inception 之前&#xff0c;大部分流行的卷积神经网络仅仅是把卷积层堆叠得越来越多&#xff0c;使得网络越来越深。这使得网络越来越复杂…

计算机组成原理-中央处理器-控制器功能和原理

目录 一、硬布线控制器 二、硬布线控制器的设计(硬件) 2.1分析每个阶段的微操作序列(取址、间址、执行、中断) 2.2选择cpu的控制方式 2.3 安排微操作时序 2.4电路设计 2.4.1列出操作时间表 2.4.2 写出微操作命令的最简表达式 2.4.3画出电路图 *三、微程序控制器基本原理 四…

剪映 自动打关键帧 AutoHotkey

牙叔教程 简单易懂 明确目的 做小说推文的话&#xff0c; 前面几分钟肯定要自己打关键帧&#xff0c; 所以这里的自动打关键帧指的是后面几分钟的图片&#xff0c; 对关键帧要求比较高的同学可以划走了, 因为这里介绍的是简单的 上上下下缩放的关键帧 要求 用剪映提取字幕…

【Python Twisted】零基础也能轻松掌握的学习路线与参考资料

Python Twisted是一个用于网络编程的事件驱动的框架&#xff0c;该框架使用异步I/O模型和回调函数。它支持多种协议&#xff0c;包括TCP、UDP、SSL/TLS、XMPP等&#xff0c;可以用来编写Web服务器、聊天应用、邮件服务器等。Twisted是一个成熟的框架&#xff0c;拥有强大的社区…

【JavaEE】文件操作和IO

目录 1、认识文件 1.1、路径 1.1.1 、绝对路径 1.1.2、相对路径 1.2、文本文件 vs 二进制文件 2、文件系统操作 3、文件内容操作 3.1、字节流用来输入的抽象类InputStream的方法使用 3.1.1、FileInputStream类的构造方法 3.1.2、字节流读操作 3.1.3、字节流写操作 3.…

Presto从入门到精通以及案例实操系列

1、简介 1.1、Presto的由来 Presto最初由Facebook公司开发&#xff0c;旨在解决Facebook内部大规模数据处理和数据分析的问题。在传统的Hadoop生态圈中&#xff0c;MapReduce作为数据处理框架&#xff0c;虽然能够处理海量数据&#xff0c;但是其查询性能却比较低下&#xff…

《面试1v1》CountDownLatch和CyclicBarrier

我是 javapub&#xff0c;一名 Markdown 程序员从&#x1f468;‍&#x1f4bb;&#xff0c;八股文种子选手。 面试官&#xff1a; 你用过 CountDownLatch 和 CyclicBarrier 吗&#xff1f; 候选人&#xff1a; 当然可以。CountDownLatch 和 CyclicBarrier 都是 Java 中用于多…

通过 docker-compose 快速部署 MySQL保姆级教程

文章目录 一、概述二、前期准备1&#xff09;部署 docker2&#xff09;部署 docker-compose 三、创建网络四、MySQL 编排部署1&#xff09;构建镜像 Dockerfile2&#xff09;配置文件2&#xff09;编排 docker-compose.yaml3&#xff09;开始部署 五、简单测试验证六、常用的 M…