动态规划c++

1. 什么是动态规划动态规划

(英语:Dynamic programming,简称 DP),是一种在数学、管理科学、计算机科学、经济学和生物信息学中使用的,通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。动态规划常常适用于有重叠子问题和最优子结构性质的问题。

1.1 重叠子问题与最优子结构

1.1.1 重叠子问题

重叠子问题是指在问题的求解过程中,存在多次使用相同的子问题的情况,即在求解问题的不同阶段,需要求解的子问题可能是相同的。重叠子问题是动态规划算法设计的基础之一,利用子问题的重叠性可以减少重复计算,提高算法效率。

1.1.2 最优子结构

最优子结构是指问题的最优解可以通过子问题的最优解来构造得到。也就是说,问题的最优解包含子问题的最优解。通俗地说,就是大问题的最优解可以由小问题的最优解推出。这是动态规划的关键性质之一。

1.1.3 举例

举个例子,假设有一个包含n个元素的序列,需要找出其中的最长递增子序列(LIS,Longest Increasing Subsequence)。这个问题就具有最优子结构性质。如果一个序列的LIS已知,那么如果在其末尾添加一个元素,就有两种情况:

1.如果该元素大于当前LIS的末尾元素,那么新序列的LIS为当前LIS加上这个元素,长度为原序列的LIS长度加1;
2.如果该元素小于等于当前LIS的末尾元素,那么当前LIS不会受到影响,新序列的LIS仍然是原序列的LIS。

因此,该问题的最优解可以通过已知的子问题的最优解构造得到。

1.2 动态规划的核心思想

动态规划最核心的思想,就在于拆分子问题,记住过往,减少重复计算。

我们来看下,网上比较流行的一个例子:

A : "1+1+1+1+1+1+1+1 =?"
A : "上面等式的值是多少"
B : 计算 "8"
A : 在上面等式的左边写上 "1+" 呢?
A : "此时等式的值为多少"
B : 很快得出答案 "9"
A : "你怎么这么快就知道答案了"
A : "只要在8的基础上加1就行了"
A : "所以你不用重新计算,因为你记住了第一个等式的值为8!动态规划算法也可以说是 '记住求过的解来节省时间'"

1.3 从青蛙跳台阶进入动态规划

leetcode原题:一只青蛙一次可以跳上1级台阶,也可以跳上2级台阶。求该青蛙跳上一个 10 级的台阶总共有多少种跳法

1.3.1 解题思路

基本思想:动态规划从较小问题的解,由交叠性质,逐步决策出较大问题的解,它是从f(1)往f(10)方向,往上推求解,所以称为自底向上的解法。

什么意思,我们从第一个台阶往上推,假设跳到第n级台阶的跳数我们定义为f(n):

1.当只有1级台阶时,只有一种跳法,即f(1)= 1;
2.当只有2级台阶时,有两种跳法。第一种是直接跳两级。第二种是先跳一级,然后再跳一级。即f(2) = 2;
3.当有3级台阶时,也有两种跳法。第一种是从第1级台阶直接跳两级。第二种是从第2级台阶跳一级。即f(3) = f(1) + f(2);
4.要想跳到第4级台阶,要么是先跳到第3级,然后再跳1级台阶上去;要么是先跳到第2级,然后一次迈2级台阶上去。即f(4) = f(2) + f(3);

此时,我门就能得到公式:

f(1) = 1;
f(2) = 2;
f(3) = f(1) + f(2);
f(4) = f(2) + f(3);

f(10) = f(8) + f(9);
即f(n) = f(n - 2) + f(n - 1)。

此时我们来看看动态规划的典型特征在此题中的展现:

1.最优子结构:f(n-1)和f(n-2) 称为 f(n) 的最优子结构。
2.重叠子问题:比如f(10)= f(9)+f(8),f(9) = f(8) + f(7) ,f(8)就是重叠子问题。
3.状态转移方程:f(n)= f(n-1)+f(n-2)就称为状态转移方程。
4.边界:f(1) = 1, f(2) = 2 就是边界。

1.3.2 代码

代码思路如图:


代码实现:

class Solution {
public:int numWays(int n) {int dp[101] = {0};int mod = 1000000007;dp[0] = 1;dp[1] = 1;dp[2] = 2;for (int i = 3; i <= n; i++) {dp[i] = dp[i - 1] + dp[i - 2];dp[i] %= mod;}return dp[n] % mod;}
};


这个方法空间复杂度是O(n),但是呢,仔细观察上图,可以发现,f(n)只依赖前面两个数,所以只需要两个变量a和b来存储,就可以满足需求了,因此空间复杂度是O(1)就可以啦。


代码实现:

class Solution {
public:int numWays(int n) {if (n < 2) {return 1;}if (n == 2) {return 2;}int a = 1;int b = 2;int temp = 0;for (int i = 3; i <= n; i++) {temp = (a + b)% 1000000007;a = b;b = temp;}return temp;}
};


2. 动态规划解题套路

2.1 核心思想

动态规划的核心思想就是拆分子问题,记住过往,减少重复计算。 并且动态规划一般都是自底向上的,因此到这里,基于青蛙跳阶问题,总结了一下做动态规划的思路:

1.穷举分析
2.确定边界
3.找出规律,确定最优子结构
4.写出状态转移方程

2.1.1按例分析

1.穷举分析
(1)当台阶数是1的时候,有一种跳法,f(1) =1)
(2)当只有2级台阶时,有两种跳法,第一种是直接跳两级,第二种是先跳一级,然后再跳一级。即f(2) = 2;
(3)当台阶是3级时,想跳到第3级台阶,要么是先跳到第2级,然后再跳1级台阶上去,要么是先跳到第 1级,然后一次迈 2 级台阶上去。所以f(3) = f(2) + f(1) =3
(4)当台阶是4级时,想跳到第3级台阶,要么是先跳到第3级,然后再跳1级台阶上去,要么是先跳到第 2级,然后一次迈 2 级台阶上去。所以f(4) = f(3) + f(2) =5
(5)当台阶是5级时…

2.确定边界
通过穷举分析,我们发现,当台阶数是1的时候或者2的时候,可以明确知道青蛙跳法。f(1) =1,f(2) = 2,当台阶n>=3时,已经呈现出规律f(3) = f(2) + f(1) =3,因此f(1) =1,f(2) = 2就是青蛙跳阶的边界。

3.找规律,确定最优子结构
n>=3时,已经呈现出规律 f(n) = f(n-1) + f(n-2) ,因此,f(n-1)和f(n-2) 称为 f(n) 的最优子结构。什么是最优子结构?有这么一个解释:

一道动态规划问题,其实就是一个递推问题。假设当前决策结果是f(n),则最优子结构就是要让 f(n-k) 最优,最优子结构性质就是能让转移到n的状态是最优的,并且与后面的决策没有关系,即让后面的决策安心地使用前面的局部最优解的一种性质

4.通过前面3步,穷举分析,确定边界,最优子结构,我们就可以得出状态转移方程啦:


3. 例题

3.1 递增子序列

3.1.1. 穷举分析:

1.当nums只有10的时候,最长子序列[10],长度1。
2.当nums加入9时,最长子序列[10]或[9],长度1。
3.当nums加入2时,最长子序列[10]或[9]或[2],长度1。
4.当nums加入5时,最长子序列[2, 5],长度2。
5.当nums加入3时,最长子序列[2, 5]或[2, 3],长度2。
6.当nums加入7时,最长子序列[2, 5, 7]或[2, 3, 7],长度3。

7.当nums再加入一个元素18时,最长递增子序列是[2,5,7,101]或者[2,3,7,101]或者[2,5,7,18]或者[2,3,7,18],长度是4。

3.1.2 确定边界

对于nums数组的每一个元素而言,当我们还没有开始遍历寻找时,它们的初始最长子序列就是它们本身长度为1。

3.1.3 找规律,确定最优子结构

通过上面分析,我们可以发现一个规律:

nums[i]结尾的自增子序列,只要找到结尾nums[j]比nums[i]小的子序列,加上nums[i] 就可以。显然,可能形成多种新的子序列,我们选最长那个,就是的最长递增子序列。

得到最优子结构:

最长递增子序列(nums[i]) = max(最长递增子序列(nums[j])) + nums[i]; 0<= j < i, nums[j] < nums[i];

3.1.4 写出状态转移方程

我们设立dp数组储存以nums数组的元素结尾的最长子序列的长度,将其初始化为1,由最优子结构得到状态转移方程:

dp[i] = max(dp[j]) + 1; 0<= j < i, nums[j] < nums[i];3.1.5 代码
class Solution {
public:int lengthOfLIS(vector<int>& nums) {vector<int> dp(nums.size(), 1);int ans = 1;for (int i = 1; i < nums.size(); i++) {for (int j = 0; j < i; j++) {if (nums[j] < nums[i]) {dp[i] = max(dp[i], dp[j] + 1);}}ans = max(ans, dp[i]);}return ans;}
};

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[Vue 代码模板] Vue3 中使用 Tailwind CSS + NutUI 实现侧边工具栏切换主题

文章归档&#xff1a;https://www.yuque.com/u27599042/coding_star/vzkgy6gvcnpl3u2y 效果示例 配置 src 目录别名 https://www.yuque.com/u27599042/coding_star/ogu2bhefy1fvahfv 配置 Tailwind CSS https://www.yuque.com/u27599042/coding_star/yqzi9olphko9ity1 配置…

绕过类安全问题分析方法

什么是绕过 逻辑漏洞是指程序设计中逻辑不严密&#xff0c;使攻击者能篡改、绕过或中断程序&#xff0c;令其偏离开发人员预期的执行。 常见表现形式 1、接口&#xff08;功能类&#xff09;绕过&#xff1a;即接口或功能中通过某参数&#xff0c;绕过程序校验 2、流程类绕…

9.jvm调优相关工具-java自带

目录 概述jdk工具包jpsjps -qjps -mjps -vjps -l jstatjstat -gcjstat -gcutiljinfo jmapjmap heapjmap histo[:live]jmap clstatsjmap dump jhatjstack 结束 概述 做了一些 1.8 与1.17.x jdk对比&#xff0c;最重要的是实际操作一次。 这些是java自带的命令&#xff0c;属于离…

wpf devexpress添加TreeListControl到项目

此教程示范如何添加TreeListControl到项目和绑定控件自引用数据源&#xff1a; 添加数据模型 绑定tree&#xff0c;并添加如下字段到数据源对象&#xff1a; Key字段包含唯一值索引节点 Parent字段包含父索引节点 添加数据模型&#xff08;Employee和Staff类&#xff09;到…

2023年中国涂料树脂需求量、市场规模及行业竞争现状分析[图]

涂料用树脂是涂料的主要原材料&#xff0c;是涂料的主要成膜物&#xff0c;且了为涂料成品提供耐醇、耐磨、耐高温、耐高湿、减少涂料在涂装完成后的损耗、保持涂装后外观以及性状的稳定性等功能。 根据生产产品的性状不同&#xff0c;其下游产品&#xff0c;即涂料成品广泛应用…

Linux使用Docker完整安装Superset3,同时解决please use superset_config.py to override it报错

文章目录 Docker安装Superset流程1. 首先获取镜像2. 生成SSL3. 创建Superset容器4. 更新数据库5. 测试访问Superset Docker安装Superset流程 1. 首先获取镜像 docker pull amancevice/superset2. 生成SSL 接下来我们运行一些额外的程序&#xff1a; openssl rand -base64 4…

电脑监控软,电脑屏幕监控软件

电脑监控软&#xff0c;电脑屏幕监控软件 电脑屏幕监控软件不仅仅是一种工具&#xff0c;更是一种守护。随着互联网的发展&#xff0c;我们工作越来越离不开电脑&#xff0c;但同时&#xff0c;也面临着更多的安全隐患。为了保护个人隐私&#xff0c;提高工作效率&#xff0c;…

canvas画点、线

效果图如下&#xff1a; <template><canvas ref"canvas" class"canvas" width"800" height"600"></canvas><hr /><button id"boldBtn" type"button" ref"boldBtn" click&qu…

【自留地】后端 - PHP - MySQL - Nginx - Python - Java

PHP ThinkPHP6入门手册 【精选】【汇总】ThinkPHP6入门手册_tp6手册_Rudon滨海渔村的博客-CSDN博客文章浏览阅读5.4k次。安装安装Composer【win】https://getcomposer.org/Composer-Setup.exe【Linux & MacOS】curl -sS https://getcomposer.org/installer | phpmv compo…

MPN – 制造零件号

S/4 1610 中的 MPN – 基于 NAST 的输出管理 我试图查找有关 MPN 设置的信息&#xff0c;但找不到详细的配置步骤。在浏览了一些信息和 help.sap 链接后&#xff0c;我能够在 S/4 1610 系统中配置 MPN 设置&#xff0c;这与使用旧输出类型&#xff08;Nast 和输出类型 NEU&…

有能一键批量转换,轻松将PDF、图片转为Word/Excel的软件吗?

随着数字化时代的到来&#xff0c;OCR技术在我们的生活中变得越来越重要。无论是从图片中提取文字&#xff0c;还是将PDF、图片格式的文件转换为Word或Excel格式&#xff0c;OCR软件都能够为我们提供极大的便利。然而&#xff0c;市面上的OCR软件种类繁多&#xff0c;哪一款软件…

2023年咸阳市《网络建设与运维》赛题解析------四、安全配置

安全配置 说明:IP地址按照题目给定的顺序用“ip/mask”表示,IPv4 any地址用0.0.0.0/0,IPv6 any地址用::/0,禁止用地址条目,否则按零分处理。 1.FW1配置IPv4 nat,实现集团产品1段IPv4访问Internet IPv4,转换ip/mask为200.200.200.16/28,保证每一个源IP产生的所有会话将…