动态规划算法,完全零基础小白教程!不是计算机的都能学会!万字吐血详解。

目录

一、动态规划算法概念

 题一

1、算法解析

1)确定状态:

​2)状态转移方程:

​3)初始化:

4)填表顺序:

5)返回值:

2、代码

题二

1、算法解析

1、确定状态

2、状态转移方程

3、初始化

4、填表顺序

5、返回值

2、代码

3、空间优化版本

 题三

1、算法解析

1、确定状态:

2、状态转移方程:

3、初始化:

4、填表顺序:

5、返回值:

2、代码

  题四

1、算法解析

1、确定状态:

2、状态转移方程:

3、初始化:

4、填表顺序:

5、返回值:

2、代码


一、动态规划算法概念

首先,什么是动态规划?
很简单,就是动态的规划。呃.....
概念名不要紧,重要的是理解其算法思想,并且能够灵活的运用其思想和方法来处理和解决现实生活中的问题,即改造世界。
动态规划的思想,具有很强的抽象性,例如什么重复子结构、最优子结构等等,你一听就晕了,这什么玩意?
一般来说,学校的课程教学,很学院派。通常是直接灌输式的给你一个世界观和方法论,然后直接让你去屠龙。
这个是一个超越经验的东西,直接给你了。但是,我们并不能理解这个结论,因为太抽象。
算法是一个由很多具体问题,经过长期总结归纳而形成的一个经验过程。算法思想算法思想,为什么不是算法公式呢?这是因为无法统一,只能是思想。
需要结合很多具体的实际问题来进行,来体会,来联系,来加深理解。
因此,在我的算法栏目中,是不会直接给你丢一堆归纳性理论的,而是,先告诉你是什么
然后再告诉你要怎么做。多做题,在这个过程中,你需要自己领悟体会。
体会什么?通过许多例题的解决过程,慢慢形成经验的直觉,再去变通,举一反三,而后融会贯通。
同志,共勉之。

下面我们直接上手,我会给你一个固定的,过程性解决问题的套路模板。
然后你根据这个模板,去套题目,找出相关的变量和关键因素。
再根据此去写代码。
动态规划,一般分为5个步骤:

1、确定状态:
刚开始一般会先画一个dp表,再去填表,某一个位置的值就是解

这一步要做的就是:明确dp数组里面的值所表示的含义
就是 dp[i] 这个值,是什么意思?
那么,怎么定义状表示呢?
这个要根据题目要求具体分析
一般来说,一维数组的状态表示,有两种:
以i为结尾,如何如何;或者以i为起点,如何如何。

2、状态转移方程:
状态转移方程就是:dp[i] 等于什么
一般来说,状态转移方程,就是根据 dp[ i ] 之前或者 dp[ i ] 之后,来推导出 dp[ i ] 的值
只要你能根据之前或或者之后的值来推导出 dp[ i ] 的值
那么,状态转移方程就出来了
但是,怎么推?
这个就要就题目而言
但是,大体的思路是这样的:根据最近的状态来划分问题
一般来说,dp[i] 的值,要么是前面的 dp[i-1] 或者后面的 dp[i+1]

3、初始化:
初始化就是保证,在我们进行填表的时候不越界
例如说,我要求 dp[0] / dp[1] 的值,需要前面的位置,但是此时明显已经越界
因此,这两个位置需要单独处理

4、填表顺序:
什么是填表顺序?
很好理解,例如说
i位置值得求解,需要前面两个位置的值已经存在才能求解
因此,也就是说在算i位置时,i-1 和 i-2 位置已经填了,已经有值了
所以,我们的填表顺序应该是从前往后,因为后面的值的求解需要前面的值
反之,就是从后往前。

5、返回值:
就是看你要dp数组的哪个位置的值,
题目要去要什么值,你就根据题目给他return就好。
这个很好理解吧?

6、代码书写
动态规划的代码书写过程是比较固定的,一般来说就分成四个步骤:
1)创建dp表
2)初始化
3)填表
4)确定返回值

7、空间优化:
空间优化就是不需要那么多空间,就可以实现目的。
怎么实现呢?
滚动数组:从左向右赋值还是从右向左赋值
这个在后面的题目中会提到。

ok,讲到这里,你懂了吗?
没听懂?那就对了。
下面跟着我来,很简单,放轻松。
我会带你把这些套路用上,去分析解决问题,跟着我的思路就好。
前面比较简单的题目我会给的非常细致,后面逐渐粗略。

 题一

746. 使用最小花费爬楼梯 - 力扣(LeetCode)

1、算法解析

1)确定状态:

确定状态是在干什么?
就是确定状态dp数组中的值代表什么含义。根据分析,我们发现:

状态表的dp[i]值是到达该位置的最小花费


2)状态转移方程:

一般来说,状态转移方程,就是根据i位置之前或者i位置之后,来推导出i的值
只要你能根据之前或或者之后的值来推导出i的值
那么,状态转移方程就出来了
但是,怎么推?
这个就要就题目而言
但是,大体的思路是这样的:根据最近的状态来划分问题

在这个题目中,我们第 i 位置的值,需要前面两个位置的值来确定,其分析过程如下:


3)初始化:

初始化就是保证,在我们进行填表的时候不越界
例如说,我要求dp[0]/dp[1]位置的值,需要前面的位置,但是此时明显已经越界
因此,这两个位置需要单独处理

4)填表顺序:

什么是填表顺序?
很好理解,例如说本题
i位置值得求解,需要前面两个位置的值已经存在才能求解
因此,也就是说在算i位置时,i-1 和 i-2 位置已经填了,已经有值了
所以,在这个题中,我们的填表顺序应该是从前往后,因为后面的值的求解需要前面的值


5)返回值:

因为我们要的是跨过所有台阶,所以这里的返回值是一维数组第n个位置的值
因此,返回值即dp[n]

2、代码

class Solution {
public:int minCostClimbingStairs(vector<int>& cost) {//创建dp表(我们要返回n位置,多创建一个位置)int n = cost.size();vector<int> dp(n+1);//初始化(走到0和走到1,是不需要花费的)dp[0] = 0;dp[1] = 0;//填表  for(int i = 2; i<=n; ++i){dp[i] = min((dp[i-1] + cost[i-1]), (dp[i-2] + cost[ i-2 ]));}//确定返回值return dp[n];}
};

题二

1137. 第 N 个泰波那契数 - 力扣(LeetCode)

1、算法解析


你自己根据我第一题的过程,自己照着求解一般,然后写出代码。

1、确定状态

确定状态是在干什么?
就是确定状态dp数组中的值代表什么含义
dp表里某个位置值的状态就是题目的解

2、状态转移方程

dp[i] = dp[i-1] + dp[i-2] + ap[i-3];题目都直接给了

3、初始化

保证填表的时候越界
根据状态表示方程进行填表
状态方程是dp[i] = dp[i-1] + dp[i-2] + ap[i-3];
因此当i小于3的时候,越界
因此,初始化状态表,dp[0] = 0;dp[1] = ap[2] = 1;

4、填表顺序

从左往右填表,因为第n个位置的值,需要前面三个值已经计算好。

5、返回值

结果是第n个位置的值
所以,返回值就是dp[n](因此需要多创建一个位置的空间)
 

2、代码

class Solution {
public:int tribonacci(int n) {if(n == 0) return 0;if(n == 1|| n == 2) return 1;//1、创建dp表vector<int> dp(n + 1);//2、初始化dp[0] = 0;dp[1] = dp[2] = 1;//3、填表for(int i = 3; i<=n; i++ )dp[i] = dp[i-1] + dp[i-2] + dp[i-3];//4、确定返回值return dp[n];        }
};

3、空间优化版本

//空间优化版本
class Solution {
public:int tribonacci(int n) {if(n == 0) return 0;if(n == 1|| n == 2) return 1;int a = 0, b = 1, c = 1, d = 0;for(int i = 3; i <=n;i++){d = a+b+c;a = b;b = c;c = d;}return d;}
};

 题三

面试题 08.01. 三步问题 - 力扣(LeetCode)

1、算法解析

1、确定状态:

定义 dp[i] 数组中的值到底表示什么意思?
很简单,根据题目,就是到达该台阶一共有多少种走法。
我们的目标是求解 dp[n],即上到第 n 阶台阶的方式数量。

2、状态转移方程:

考虑小孩每次可以走 1 阶、2 阶或 3 阶:

因此,状态转移方程为:
dp[i] = dp[i-1] + dp[i-2] + dp[i-3]

3、初始化:

dp[0] = 1:上到第 0 阶只有一种方式,就是不走任何台阶。
dp[1] = 1:上到第 1 阶只有一种方式,就是从地面直接走一阶。
dp[2] = 2:上到第 2 阶有两种方式,可以走两次一阶或者一次两阶。
为什么初始化这三个位置?因为他们需要前面三个位置的值,如果不初始化,会越界。

4、填表顺序:

从 dp[3] 开始一直填充到 dp[n]。

5、返回值:

返回 dp[n],因此要多创建一个位置的空间,同时由于结果可能很大,要对 dp[n] 模 1000000007 取余。

2、代码

class Solution {
public:int waysToStep(int n) {if(n == 1) return 1;if(n == 2) return 2;// 1、创建dp表vector<int> dp(n + 1);// 2、初始化dp[0] = 1;dp[1] = 1;dp[2] = 2;// 3、填表for(int i = 3; i<n+1; ++i)dp[i] = ((dp[i-1] + dp[i-2]) % 1000000007 + dp[i-3]) % 1000000007;// 4、确定返回值return dp[n];}
};

  题四

91. 解码方法 - 力扣(LeetCode)

1、算法解析

1、确定状态:

定义 dp[i] 数组中的值到底表示什么意思:dp[i]的值,就是以i为结尾的编码串的最多解码方式

2、状态转移方程:

因此,状态转移方程为:
dp[i] = dp[i-1] + dp[i-2] 

3、初始化:

为什么初始化这几个位置?因为他们需要前面三个位置的值,如果不初始化,会越界。

4、填表顺序:

从 dp[3] 开始一直填充到 dp[n]。

5、返回值:

返回 dp[n]

2、代码

class Solution {
public:int numDecodings(string s) {//1、创建dp表int n = s.size();vector<int> dp(n);//只有一位dp[0] = s[0] == '0' ? 0 : 1;if(n == 1 ) return dp[0];//2、初始化//根据判断条件进行初始化if(s[0] != '0' && s[1] != '0') dp[1]++;int m = (s[0] - '0')*10 + (s[1] - '0');//组合编码if(m>=10 && m <= 26)dp[1] ++;//3、填表for(int i = 2; i<n; ++i){//i位置单独编码if( s[i] != '0') dp[i] += dp[i-1];//i和i-1位置组合编码int x = (s[i-1] - '0')*10 + (s[i] - '0');if(x >= 10 && x <= 26) dp[i] += dp[i-2];}//4、返回值return dp[n-1];}
};

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

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

相关文章

如何理解MySql的MVCC机制

MVCC是什么 MySQL的MVCC机制&#xff0c;全称为多版本并发控制&#xff08;Multi-VersionConcurrency Control&#xff09;&#xff0c;是一种提高数据库并发性能的技术。MVCC的主要目的是在保证数据一致性的同时&#xff0c;提高数据库的并发性能。 它通过为每个读操作创建数…

智能版面设计:指令跟随模型在自动布局规划中的应用

在广告行业一个吸引人的视觉布局能够显著提升信息的传播效果。但对于非专业设计师来说&#xff0c;创建既美观又功能性强的布局常常是一项挑战。他们往往缺乏必要的设计技能、审美训练或资源来快速实现创意构想。传统的设计软件和在线工具虽然提供了一些模板和指导&#xff0c;…

vue3-openlayers marker 光晕扩散(光环扩散)(postrender 事件和 render 方法)

本篇介绍一下使用 vue3-openlayers marker 光晕扩散&#xff08;光环扩散&#xff09;&#xff08;postrender 事件和 render 方法&#xff09; 1 需求 marker 光晕扩散&#xff08;光环扩散&#xff09; 2 分析 marker 光晕扩散&#xff08;光环扩散&#xff09;使用 post…

SPI NAND、SD NAND和eMMC对比—MK米客方德

目录 1. 容量: 2.封装类型&#xff1a; 3.速度: 4.性能: 5.寿命: 6. 使用方式: 7. 其他优缺点: 8.常见应用场景: 1. 容量: SPI NAND通常提供从几百MB到几GB的存储容量。 SD NAND的容量覆盖范围比SPI NAND更广&#xff0c;从几GB到几十GB不等。 eMMC的容量范围更大&a…

代码随想录第41天|动态规划

322. 零钱兑换 dp[j] : 最小硬币数量, j 为金额(相当于背包空间)递推公式 : dp[j] min(dp[j - coins[i]] 1, dp[j])初始化: 需要一个最大值, 避免覆盖, dp[0] 0遍历顺序: 钱币有序无序不影响, 因为求解最小个数, 结果相同(先遍历物品后背包, 先背包后物品都可) class Solut…

怎样在《语文世界》期刊上发表论文?

怎样在《语文世界》期刊上发表论文&#xff1f; 《语文世界》知网国家级 1.5-2版 2500字符左右 正常收25年4-6月版面 可加急24年内&#xff08;初中&#xff0c;高中&#xff0c;中职&#xff0c;高职&#xff0c;大学均可&#xff0c;操作周期2个月左右&#xff09; 《语文世…

【084】基于SpringBoot实现的家乡特色推荐系统

系统介绍 视频演示 点击查看演示视频 基于SpringBoot实现的家乡特色推荐系统主要采用SpringBootVue进行开发&#xff0c;系统整体分为管理员、用户两种角色&#xff0c;主要功能包括首页&#xff0c;个人中心&#xff0c;用户管理&#xff0c;文章分类管理&#xff0c;文章分…

C语言结构体深入解析【结构体嵌套结构体,结构体变量和指针,结构体和函数,计算结构体大小,结构体数组,结构体成员的访问,结构体与联合】

C语言结构体深入解析 目录 C语言结构体深入解析前言结构体的定义结构体在内存中的表示结构体变量初始化直接定义并初始化使用自己定义的结构体变量初始化新变量结构体数组初始化 结构体中嵌套结构体结构体成员访问点操作符(.)箭头操作符(->) 结构体变量和指针结构体指针定义…

@RequestMapping属性详解及案例演示

RequestMapping源码 Target({ElementType.TYPE, ElementType.METHOD}) Retention(RetentionPolicy.RUNTIME) Documented Mapping public interface RequestMapping {String name() default "";AliasFor("path")String[] value() default {};AliasFor(&quo…

智能写作与痕迹消除:AI在创意文案和论文去痕中的应用

作为一名AI爱好者&#xff0c;我积累了许多实用的AI生成工具。今天&#xff0c;我想分享一些我经常使用的工具&#xff0c;这些工具不仅能帮助提升工作效率&#xff0c;还能激发创意思维。 我们都知道&#xff0c;随着技术的进步&#xff0c;AI生成工具已经变得越来越智能&…

简单分享 for循环,从基础到高级

1. 基础篇&#xff1a;Hello, For Loop! 想象一下&#xff0c;你想给班上的每位同学发送“Hello!”&#xff0c;怎么办&#xff1f;那就是for循环啦&#xff0c; eg&#xff1a;首先有个名字的列表&#xff0c;for循环取出&#xff0c;分别打印 names ["Alice", …

bigNumber的部分使用方法与属性

场景&#xff1a;最近做IoT项目的时候碰到一个问题&#xff0c;涉及到双精度浮点型的数据范围的校验问题。业务上其实有三种类型&#xff1a;int、float和double类型三种。他们的范围分别是&#xff1a; //int int: [-2147483648, 2147483647],//float float: [-3402823466385…

PHP7源码结构

PHP7程序的执行过程 1.PHP代码经过词法分析转换为有意义的Token&#xff1b; 2.Token经过语法分析生成AST&#xff08;Abstract Synstract Syntax Tree&#xff0c;抽象语法树&#xff09;&#xff1b; 3.AST生成对应的opcode&#xff0c;被虚拟机执行。 源码结构&#xff1…

一切为了安全丨2024中国应急(消防)品牌巡展武汉站成功召开!

消防品牌巡展武汉站 6月28日&#xff0c;由中国安全产业协会指导&#xff0c;中国安全产业协会应急创新分会、应急救援产业网联合主办&#xff0c;湖北消防协会协办的“一切为了安全”2024年中国应急(消防)品牌巡展-武汉站成功举办。该巡展旨在展示中国应急&#xff08;消防&am…

qt QTreeView的简单使用(多级子节点)

MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow) {ui->setupUi(this);setWindowTitle("QTreeView的简单使用");model new QStandardItemModel;model->setHorizontalHeaderLabels(QStringList() << "left&q…

[leetcode]longest-arithmetic-subsequence-of-given-difference. 最长定差子序列

. - 力扣&#xff08;LeetCode&#xff09; class Solution { public:int longestSubsequence(vector<int> &arr, int difference) {int ans 0;unordered_map<int, int> dp;for (int v: arr) {dp[v] dp[v - difference] 1;ans max(ans, dp[v]);}return ans…

Qt源码分析:窗体绘制与响应

作为一套开源跨平台的UI代码库&#xff0c;窗体绘制与响应自然是最为基本的功能。在前面的博文中&#xff0c;已就Qt中的元对象系统(反射机制)、事件循环等基础内容进行了分析&#xff0c;并捎带阐述了窗体响应相关的内容。因此&#xff0c;本文着重分析Qt中窗体绘制相关的内容…

如何完成域名解析验证

一&#xff1a;什么是DNS解析&#xff1a; DNS解析是互联网上将人类可读的域名&#xff08;如www.example.com&#xff09;转换为计算机可识别的IP地址&#xff08;如192.0.2.1&#xff09;的过程&#xff0c;大致遵循以下步骤&#xff1a; 查询本地缓存&#xff1a;当用户尝…

顺序串算法库构建

学习贺利坚老师顺序串算法库 数据结构之自建算法库——顺序串_创建顺序串s1,创建顺序串s2-CSDN博客 本人详细解析博客 串的概念及操作_串的基本操作-CSDN博客 版本更新日志 V1.0: 在贺利坚老师算法库指导下, 结合本人详细解析博客思路基础上,进行测试, 加入异常弹出信息 v1.0补…

已解决java.awt.geom.NoninvertibleTransformException:在Java2D中无法逆转的转换的正确解决方法,亲测有效!!!

已解决java.awt.geom.NoninvertibleTransformException&#xff1a;在Java2D中无法逆转的转换的正确解决方法&#xff0c;亲测有效&#xff01;&#xff01;&#xff01; 目录 问题分析 出现问题的场景 报错原因 解决思路 解决方法 1. 检查缩放因子 修改后的缩放变换 …