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

news2024/10/6 23:12:01

目录

一、动态规划算法概念

 题一

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.coloradmin.cn/o/1887009.html

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

相关文章

你喜欢波段交易吗?

波段交易的核心在于精准捕捉市场中的长期趋势波动&#xff0c;以实现更为稳健的收益。与剥头皮和日内交易不同&#xff0c;波段交易者更倾向于持有交易头寸数日乃至数周&#xff0c;以更宽广的视角把握市场动态。 这种交易方式的优势在于&#xff0c;它降低了对即时市场反应的…

C - Popcorn(abs358)

题意&#xff1a;有n个摊子&#xff0c;m个爆米花&#xff0c;想花费最少去的店铺买到所有的口味的爆米花&#xff0c;找到每一列都为‘o’的最少行数。 分析&#xff1a;用dfs寻找最少路径 #include<bits/stdc.h> using namespace std; typedef long long ll; char x;…

【面试系列】AI研究员高频面试题及详细解答

欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;欢迎订阅相关专栏&#xff1a; ⭐️ 全网最全IT互联网公司面试宝典&#xff1a;收集整理全网各大IT互联网公司技术、项目、HR面试真题. ⭐️ AIGC时代的创新与未来&#xff1a;详细讲解AIGC的概念、核心技术、…

内网渗透第四天!!!冲冲冲!!怎么绕过uac以及你会all劫持???不安全的服务路径以及服务权限,你会吗???

在第三天我们简单的说了一下绕过uac&#xff0c;但是我们使用的msf模块ask要对方管理员跟我们一起来进行操作&#xff0c;才可以进行提权的操作&#xff0c;这点就限制住了我们。我们今天来讲一下不用钓鱼的绕过的操作。 绕过uac&#xff1a; 使用uacme项目和msf联动来进行绕过…

和小红书一起参会! 了解大模型与大数据融合的技术趋势

在过去的两年中&#xff0c;“大模型”无疑成为互联网行业的焦点话题&#xff0c;曾经炙手可热的大数据架构似乎淡出公众视野。然而&#xff0c;大数据领域并未停滞不前&#xff0c;反而快速演进&#xff0c;传统依赖众多开源组件的大数据平台正逐步过渡到以融合与简化为核心特…

Xorbits inference操作实战

1.操作环境 序号软件版本备注1Windows1.版本&#xff1a;Windows 10 专业版2.版本号&#xff1a;21H23.操作系统内部版本&#xff1a;19044.18892Docker Desktop4.24.2 (124339)3WSLUbuntu 22.04 LTS4Python3.105CUDA12.16Dify0.6.6 Xorbits inference 是一个强大且通用的分布…

那些好用的 Vue3 的工具搭子!!【送源码】

2020 年 9 月 18 日 Vue3 的正式发布已经过去了大约 3 年 9 个月左右&#xff01;&#xff01;&#xff01; 随着 Vue3 版本的逐渐成熟&#xff0c;我们的前端世界也迎来了一系列令人振奋的更新和工具。Vue 生态圈的持续扩大&#xff0c;无疑为前端开发人员带来了前所未有的便…

C盘清理和管理

本篇是C盘一些常用的管理方法&#xff0c;以及定期清理C盘的方法&#xff0c;大部分情况下都能避免C盘爆红。 C盘清理和管理 C盘存储管理查看存储情况清理存储存储感知清理临时文件清理不需要的 迁移存储 磁盘清理桌面存储管理应用存储管理浏览器微信 工具清理 C盘存储管理 查…

鸿蒙开发设备管理:【@ohos.multimodalInput.touchEvent (触摸输入事件)】

触摸输入事件 设备上报的触屏事件。 说明&#xff1a; 本模块首批接口从API version 9开始支持。后续版本的新增接口&#xff0c;采用上角标单独标记接口的起始版本。 导入模块 import {Action,ToolType,SourceType,Touch,TouchEvent} from ohos.multimodalInput.touchEvent;…

【Redis7】零基础篇

1 课程概述 2 Redis入门概述 2.1 是什么 Redis是基于内存的KV键值对内存数据库 Redis&#xff1a;Remote Dictionary Server(远程字典服务)是完全开源的&#xff0c;使用ANSIC语言编写遵守BSD协议&#xff0c;是一个高性能的Key-Value数据库提供了丰富的数据结构&#xff0c…

STM32F1+HAL库+FreeTOTS学习3——任务创建(动态和静态两种)

STM32F1HAL库FreeTOTS学习3——任务创建&#xff08;动态和静态两种&#xff09; 任务创建API函数任务创建流程代码实现1. 动态任务创建和删除2. 静态任务创建和删除 上期我们学习了STM32移植FreeRTOS搭建基准工程&#xff0c;现在我们来学习任务创建 任务创建API函数 前面我们…

RK3568平台(USB篇)USB HID设备

一.USB HID设备简介 USB HID设备主要用于和计算机进行交互通信&#xff0c;典型的USB HID类设备包括USB键盘、USB鼠标、USB游戏手柄等等&#xff0c;这些都是日常生活中常见的设备。以USB接口的鼠标为例&#xff0c;打开计算机的“设备管理器”&#xff0c;可以在“鼠标和其他…

mac上使用finder时候,显示隐藏的文件或者文件夹

默认在finder中是不显示隐藏的文件和文件夹的&#xff0c;但是想创建.gitignore文件&#xff0c;并向里面写入内容&#xff0c;即便是打开xcode也是不显示这几个隐藏文件的&#xff0c;那有什么办法呢&#xff1f; 使用快捷键&#xff1a; 使用finder打开包含隐藏文件的文件夹…

Web缓存代理和CDN 内容分发网络

目录 1.WEB缓存代理 1.1 WEB缓存代理作用 1.2 常见WEB缓存代理 1.3 Nginx 配置 缓存代理 2. CDN内容分发网络 1.WEB缓存代理 1.1 WEB缓存代理作用 存储一些之前给访问过的&#xff0c;且可能要被再次访问的静态网页资源对象&#xff0c;使客户端可以直接从缓存代理服务器…

NSSCTF-Web题目19(数据库注入、文件上传、php非法传参)

目录 [LitCTF 2023]这是什么&#xff1f;SQL &#xff01;注一下 &#xff01; 1、题目 2、知识点 3、思路 [SWPUCTF 2023 秋季新生赛]Pingpingping 4、题目 5、知识点 6、思路 [LitCTF 2023]这是什么&#xff1f;SQL &#xff01;注一下 &#xff01; 1、题目 2、知识…

【数值计算库-超长笔记】Python-Mpmath库:高精度数值计算

原文链接&#xff1a;https://www.cnblogs.com/aksoam/p/18279394 更多精彩&#xff0c;关注博客园主页&#xff0c;不断学习&#xff01;不断进步&#xff01; 我的主页 csdn很少看私信&#xff0c;有事请b站私信 博客园主页-发文字笔记-常用 有限元鹰的主页 内容&#xf…

RTSP协议在视频监控系统中的典型应用、以及视频监控设备的rtsp地址格式介绍

目录 一、协议概述 1、定义 2、提交者 3、位置 二、主要特点 1、实时性 2、可扩展性 3、控制功能 4、回放支持 5、网络适应性 三、RTSP的工作原理 1、会话准备 2、会话建立 3、媒体流控制 4、会话终止 5、媒体数据传输 四、协议功能 1、双向性 2、带外协议 …

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

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

《昇思25天学习打卡营第9天|onereal》

继续学习昨天的 基于MindNLPMusicGen生成自己的个性化音乐 生成音乐 MusicGen支持两种生成模式&#xff1a;贪心&#xff08;greedy&#xff09;和采样&#xff08;sampling&#xff09;。在实际执行过程中&#xff0c;采样模式得到的结果要显著优于贪心模式。因此我们默认启…

实用软件分享-----一款免费的投屏软件(支持手机投屏到电脑)Aiseesoft Phone Mirror 2.2.36 x64

专栏介绍:本专栏主要分享一些实用的软件(Po Jie版); 声明1:软件不保证时效性;只能保证在写本文时,该软件是可用的;不保证后续时间该软件能一直正常运行;不保证没有bug;如果软件不可用了,我知道后会第一时间在题目上注明(已失效)。介意者请勿订阅。 声明2:本专栏的…