算法修炼之筑基篇——筑基二层中期(讨论一下如何解决动态方程问题,没时间了,快快快看一下)

news2024/11/24 8:04:22

博主:命运之光

🦄专栏:算法修炼之练气篇

🍓专栏:算法修炼之筑基篇

博主的其他文章:点击进入博主的主页

前言:学习了算法修炼之练气篇想必各位蒟蒻们的基础已经非常的扎实了,下来我们进阶到算法修炼之筑基篇的学习。筑基期和练气期难度可谓是天差地别,懂得都懂,题目难度相比起练气期的题目难度提升很多,所以要是各位蒟蒻小伙伴们看不懂筑基期的题目可以在练气期多积累积累,练气期的题目也会不断更新,大家一定要把基础打牢固了再来看筑基期的题目哈,这样子也可以提高大家的学习效率,一举两得,加油(●'◡'●)🎉🎉

目录

✨动态规划问题一般怎么解决?

✨有没有什么套路?

✨学好动态规划要学会那些基本内容

✨一些动态规划题的解题思路和标准模板,和通用状态方程

🍓最长公共子序列(Longest Common Subsequence):

🍓最长递增子序列(Longest Increasing Subsequence):

🍓最大子数组和(Maximum Subarray Sum):

🍓矩阵链相乘(Matrix Chain Multiplication):

🍓最短路径问题(Shortest Path Problem):

🍓切割钢条问题(Cutting Rod Problem):

🍓背包问题的变种:

🍓字符串编辑距离(Edit Distance):

✨结语


✨动态规划问题一般怎么解决?

动态规划(Dynamic Programming)是一种解决优化问题的算法思想,通常用于解决具有重叠子问题性质和最优子结构性质的问题。动态规划将问题分解成一系列重叠的子问题,并通过保存子问题的解来避免重复计算,从而提高算法的效率。

下面是一般解决动态规划问题的步骤:

1. 确定问题的状态:将原问题划分为若干个子问题,确定每个子问题的状态,状态一般由一些变量表示。

2. 定义状态转移方程:根据子问题之间的关系,建立状态之间的转移方程。这个转移方程描述了问题的最优解与子问题的最优解之间的关系。

3. 初始化:确定初始状态的值,一般是边界情况下的解,或者根据题目要求进行初始化。

4. 确定计算顺序:根据状态转移方程,确定计算状态的顺序。通常,需要先计算较小规模的子问题,再逐步计算规模较大的子问题。

5. 递推计算:按照计算顺序,通过状态转移方程逐步计算每个状态的值。

6. 求解原问题:根据子问题的解或最终状态的值,求解原问题的最优解。

7. 可选的优化:有些情况下,可以通过一些技巧进行进一步的优化,例如使用滚动数组、空间压缩等方法来降低空间复杂度。

总的来说,动态规划是一种自底向上的求解方法,通过将原问题拆解为子问题并利用子问题的解来求解原问题的最优解。以上是一般解决动态规划问题的步骤,具体问题需要根据实际情况进行调整和优化。

✨有没有什么套路?

在使用C/C++编写动态规划算法时,以下是一些常见的套路和技巧:

  1. 定义数组:通常情况下,动态规划算法需要定义一个二维数组或一维数组来保存子问题的解。根据问题的需要,选择合适的数组类型(如int、long long等)和大小。
  2. 初始化数组:根据问题的具体要求,对数组进行初始化。有些情况下,可以通过将数组的初始值设置为一个特殊值来标记状态为未计算或无效。
  3. 状态转移方程的实现:根据问题的状态转移方程,使用循环结构(如for循环)遍历数组,逐个计算每个状态的值。注意循环的起始位置和结束条件。
  4. 边界情况的处理:某些情况下,需要特别处理边界状态的值,例如将边界状态初始化为已知的值,或者单独处理边界状态的转移方程。
  5. 循环顺序的选择:根据问题的性质,选择合适的循环顺序。有时可以从小规模子问题开始,逐渐扩大规模;有时可以从大规模问题开始,逐步缩小规模。
  6. 空间优化:有时动态规划算法会占用较大的空间,可以考虑使用滚动数组(滑动窗口)等技巧来减少内存使用。
  7. 返回结果:根据问题的要求,返回计算得到的最优解或所需的结果。

总的来说,C/C++编写动态规划算法时,需要熟悉数组的定义和操作,灵活运用循环结构和条件语句,并注意处理边界情况和选择合适的循环顺序。对于大规模问题,可能需要考虑空间优化技巧。根据问题的具体要求,进行相应的算法设计和实现。

✨学好动态规划要学会那些基本内容

  1. 最优子结构:了解最优子结构的概念,即问题的最优解可以由子问题的最优解推导而来。
  2. 重叠子问题:理解重叠子问题的性质,即问题的求解过程中存在重复计算的子问题。
  3. 状态定义:学会确定问题的状态,将问题划分为子问题,并明确每个子问题的状态表示。
  4. 状态转移方程:学会建立子问题之间的转移关系,即确定状态之间的转移方程,描述问题的最优解与子问题的最优解之间的关系。
  5. 初始化:了解如何对问题的初始状态进行初始化,确定边界条件下的解。
  6. 计算顺序:学会确定计算状态的顺序,一般是从较小规模的子问题逐步计算到规模较大的子问题。
  7. 递推计算:熟悉利用状态转移方程进行递推计算的方法,通过保存子问题的解来避免重复计算。
  8. 求解原问题:掌握如何根据子问题的解或最终状态的值,求解原问题的最优解。
  9. 空间优化:了解一些空间优化的技巧,例如滚动数组、状态压缩等,以减少算法的内存使用。
  10. 练习和实践:动态规划需要通过大量的练习和实践来巩固和提高技能,因为每个问题都有不同的特点和解题思路。

总的来说,学好动态规划需要理解其基本概念和思想,并在实践中不断积累经验。通过解决各种不同类型的动态规划问题,可以提高对动态规划算法的理解和应用能力。

✨一些动态规划题的解题思路和标准模板,和通用状态方程

🍓最长公共子序列(Longest Common Subsequence):

  • 解题思路:使用动态规划来解决最长公共子序列问题,通常需要构建一个二维数组来保存子问题的解。从左上角开始,逐步计算每个位置的值,根据字符的匹配情况进行状态转移。
  • 通用状态方程:dp[i][j]表示字符串A的前i个字符和字符串B的前j个字符的最长公共子序列长度。
  • 标准模板:
int longestCommonSubsequence(string text1, string text2) {
    int m = text1.length();
    int n = text2.length();
    vector<vector<int>> dp(m + 1, vector<int>(n + 1, 0));
    for (int i = 1; i <= m; i++) {
        for (int j = 1; j <= n; j++) {
            if (text1[i - 1] == text2[j - 1]) {
                dp[i][j] = dp[i - 1][j - 1] + 1;
            } else {
                dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
            }
        }
    }
    return dp[m][n];
}

🍓最长递增子序列(Longest Increasing Subsequence):

  • 解题思路:使用动态规划来解决最长递增子序列问题,通常需要构建一个一维数组来保存子问题的解。遍历数组,逐个计算每个位置的最长递增子序列长度,并更新结果。
  • 通用状态方程:dp[i]表示以第i个元素结尾的最长递增子序列长度。
  • 标准模板:
int lengthOfLIS(vector<int>& nums) {
    int n = nums.size();
    vector<int> dp(n, 1);
    int maxLen = 1;
    for (int i = 1; i < n; i++) {
        for (int j = 0; j < i; j++) {
            if (nums[i] > nums[j]) {
                dp[i] = max(dp[i], dp[j] + 1);
            }
        }
        maxLen = max(maxLen, dp[i]);
    }
    return maxLen;
}

🍓最大子数组和(Maximum Subarray Sum):

  • 解题思路:使用动态规划来解决最大子数组和问题,通常需要维护一个变量来保存当前位置的最大子数组和,并不断更新。
  • 通用状态方程:dp[i]表示以第i个元素结尾的最大子数组和。
  • 标准模板:
int maxSubArray(vector<int>& nums) {
    int n = nums.size();
    vector<int> dp(n, 0);
    dp[0] = nums[0];
    int maxSum = dp[0];
    for (int i = 1; i < n; i++) {
        dp[i] = max(nums[i], dp[i - 1] + nums[i]);
        maxSum = max(maxSum, dp[i]);
    }
    return maxSum;
}

🍓矩阵链相乘(Matrix Chain Multiplication):

  • 解题思路:矩阵链相乘问题可以使用动态规划来解决。需要构建一个二维数组来保存子问题的最优解,从小规模的子问题开始逐步计算,然后根据状态转移方程更新最优解。
  • 通用状态方程:dp[i][j]表示从第i个矩阵到第j个矩阵相乘的最小代价。
  • 标准模板:
int matrixChainMultiplication(vector<int>& dimensions) {
    int n = dimensions.size();
    vector<vector<int>> dp(n, vector<int>(n, 0));
    for (int len = 2; len < n; len++) {
        for (int i = 0; i < n - len; i++) {
            int j = i + len;
            dp[i][j] = INT_MAX;
            for (int k = i + 1; k < j; k++) {
                int cost = dp[i][k] + dp[k][j] + dimensions[i] * dimensions[k] * dimensions[j];
                dp[i][j] = min(dp[i][j], cost);
            }
        }
    }
    return dp[0][n - 1];
}

🍓最短路径问题(Shortest Path Problem):

  • 解题思路:最短路径问题可以使用动态规划来解决,常用的算法是Dijkstra算法和Floyd-Warshall算法。这些算法通过构建一个二维数组来保存子问题的最优解,从小规模的子问题开始逐步计算,然后根据状态转移方程更新最优解。
  • 通用状态方程:dp[i][j]表示从顶点i到顶点j的最短路径长度。
  • 标准模板:
void shortestPath(vector<vector<int>>& graph) {
    int n = graph.size();
    vector<vector<int>> dp(graph);
    for (int k = 0; k < n; k++) {
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                if (dp[i][k] != INT_MAX && dp[k][j] != INT_MAX) {
                    dp[i][j] = min(dp[i][j], dp[i][k] + dp[k][j]);
                }
            }
        }
    }
}

🍓切割钢条问题(Cutting Rod Problem):

  • 解题思路:切割钢条问题可以使用动态规划来解决。通常使用自底向上的方法,从小段长度开始逐步计算最优解,然后根据状态转移方程更新最优解。
  • 通用状态方程:dp[i]表示长度为i的钢条的最大价值。
  • 标准模板:
int cuttingRod(vector<int>& prices, int length) {
    int n = prices.size();
    vector<int> dp(length + 1, 0);
    for (int i = 1; i <= length; i++) {
        for (int j = 1; j <= i; j++) {
            dp[i] = max(dp[i], prices[j - 1] + dp[i - j]);
        }
    }
    return dp[length];
}

🍓背包问题的变种:

  • 解题思路:背包问题有多种变种,例如分组背包、二维背包等。每种变种问题的解题思路和状态方程都有所不同,需要根据具体问题进行分析和设计。通常也是通过构建一个二维或多维数组来保存子问题的解,然后根据不同的状态转移方程更新最优解。
  • 通用状态方程:根据具体问题的不同而不同。
  • 解题模板:根据具体问题的不同而不同可以看之前的背包问题的文章。

🍓字符串编辑距离(Edit Distance):

  • 解题思路:字符串编辑距离问题可以使用动态规划来解决。通常构建一个二维数组来保存子问题的最优解,从小规模的子问题开始逐步计算,然后根据状态转移方程更新最优解。
  • 通用状态方程:dp[i][j]表示将字符串A的前i个字符转换为字符串B的前j个字符所需的最小编辑操作次数。
  • 标准模板:
int editDistance(string word1, string word2) {
    int m = word1.length();
    int n = word2.length();
    vector<vector<int>> dp(m + 1, vector<int>(n + 1, 0));
    for (int i = 1; i <= m; i++) {
        dp[i][0] = i;
    }
    for (int j = 1; j <= n; j++) {
        dp[0][j] = j;
    }
    for (int i = 1; i <= m; i++) {
        for (int j = 1; j <= n; j++) {
            if (word1[i - 1] == word2[j - 1]) {
                dp[i][j] = dp[i - 1][j - 1];
            } else {
                dp[i][j] = min({dp[i - 1][j - 1], dp[i][j - 1], dp[i - 1][j]}) + 1;
            }
        }
    }
    return dp[m][n];
}

✨结语

🍓🍓动态规划是一种令人兴奋和有趣的算法思想,通过将问题分解为子问题并保存子问题的解,我们可以高效地求解复杂问题的最优解。在本篇博客中,我们探讨了几种常见的动态规划问题,包括最长公共子序列、最长递增子序列、最大子数组和、矩阵链相乘、最短路径问题、切割钢条问题和字符串编辑距离。对于每个问题,我们提供了解题思路、通用状态方程和标准模板。

🍓🍓希望这篇博客能够让你对动态规划有一个简单而全面的了解,并且激发你在解决问题时尝试动态规划的勇气。记住,在解决动态规划问题时,关键是理解问题的性质和定义状态,然后设计合适的状态转移方程。通过不断学习和练习,你将掌握动态规划的技巧,能够灵活地应对各种问题。

🍓🍓让我们一起享受动态规划的大冒险吧!愿你在解题过程中充满欢乐和成就感。继续保持好奇心,不断探索新的解题方法和技巧,你将在编程的旅程中取得更多的成就。

感谢你的阅读,希望这篇博客对你有所帮助。祝你在动态规划的世界中玩得开心,继续热爱编程!

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

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

相关文章

使用FFmpeg实现最简单的视频播放

按照之前的编译步骤我们会编译得到使用ffmpeg需要的文件&#xff0c;现在就使用ffmpeg实现最简单的视频播放 集成ffmpeg 使用Android Studio创建一个Native C项目编译之后得到三个文件夹 把include 文件夹放到cpp目录下面。 main 目录下面新建jniLibs 目录把lib文件下的so文件…

Java之BigDecimal使用

Java之BigDecimal使用 1、BigDecimal概述 ​ BigDecimal用来对超过16位有效位的数进行精确的运算。双精度浮点型变量double可以处理16位有效数&#xff0c;但在实际应用中&#xff0c;可能需要对更大或者更小的数进行运算和处理。一般情况下&#xff0c;对于那些不需要准确计…

OA系统,企业数字化转型的重要工具,用现成还是自己搭建呢

什么是OA系统 OA系统是办公自动化系统的简称&#xff0c;它是指一种基于计算机技术的办公工作管理系统&#xff0c;用于协调和规划企业内部各部门的信息发布、通信、人员流动、文档管理等方面的工作。它可以有效地提高企业办公效率和工作效益&#xff0c;优化企业内部沟通协作…

计算机视觉 | 深度学习预训练与MMPretrain

前言 MMPretrain是一款基于pytorch的开源深度学习预训练工具箱&#xff0c;是OenMMLab的项目成员之一。它是一个全新升级的预训练开源算法框架&#xff0c;旨在提供各种强大的预训练主干网络&#xff0c;并支持了不同的预训练策略。 一、MMPretrain算法库介绍 MMPretrain 源…

几分钟上线一个应用,这个神器我爱了!

配置一套公司企业运用的SaaS工作流办公管理系统需要多久&#xff1f;需要多少人才能开发出来&#xff1f;传统软件开发起码需要10个人&#xff0c;花上个把月时间&#xff0c;才能做出一套比较完整的SaaS工作流办公管理系统。 传统的开发模式它需要前后端程序员以及各平台系统的…

【Docker】浅谈Docker之AUFS、BTRFS、ZFS、Container、分层的概念

作者简介&#xff1a; 辭七七&#xff0c;目前大一&#xff0c;正在学习C/C&#xff0c;Java&#xff0c;Python等 作者主页&#xff1a; 七七的个人主页 文章收录专栏&#xff1a; 七七的闲谈 欢迎大家点赞 &#x1f44d; 收藏 ⭐ 加关注哦&#xff01;&#x1f496;&#x1f…

【算法】--- 几分钟了解直接选择排序(排序中最简单的排序)+快排(解决一切的优质算法)(中)

文章目录 前言&#x1f31f;一、常见的排序算法&#xff1a;&#x1f31f;二、选择排序---直接选择排序&#xff1a;&#x1f30f;2.1.1 基本思想&#xff1a;&#x1f30f;2.1.2 直接选择排序:&#x1f30f;2.1.3 直接选择排序的特性总结&#xff1a;&#x1f30f;2.1.4 思路&…

Vue3 Vite4 ElementPlus TS模板(含Vue-Router4+Pinia4)

引言 手动安装配置Vue3 ElementPlus模板比较繁琐&#xff0c;网上寻找一些模板不太符合自己预期&#xff0c;因此花点精力搭建一个符合自己需求的架子 采用最新的组件&#xff0c;版本如下&#xff1a; vite 4.3.9vite-plugin-mock 2.9.8vue 3.3.4pinia 2.1.3vue-router 4.2.2…

总结6种服务限流的实现方式

服务限流&#xff0c;是指通过控制请求的速率或次数来达到保护服务的目的&#xff0c;在微服务中&#xff0c;我们通常会将它和熔断、降级搭配在一起使用&#xff0c;来避免瞬时的大量请求对系统造成负荷&#xff0c;来达到保护服务平稳运行的目的。下面就来看一看常见的6种限流…

推荐常用的排序学习算法——BPR(贝叶斯个性化排序)

文章目录 1. 排序学习1.1 优势1.2 排序学习在推荐领域的作用1.3 排序学习设计思路1.3.1 单点法&#xff08;Pointwise&#xff09;1.3.2 配对法&#xff08;Pairwise&#xff09;1.3.3 列表法&#xff08;Listwise&#xff09; 2. BPR&#xff08;贝叶斯个性化推荐&#xff09;…

投票评选活动小程序的分享功能和背景音乐功能实现

投票评选活动小程序的分享功能和背景音乐功能实现 投票评选活动过程中&#xff0c;需要转发分享出去&#xff0c;实现投票的效果&#xff0c;那么就需要分享功能&#xff0c;不然怎么实现投票呢&#xff0c;其实这个是最具价值的功能之一。 而背景音乐播放功能&#xff0c;只…

路径规划算法:基于静电放电优化的路径规划算法- 附代码

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

Qt/GUI/布局/实现窗口折叠效果/且在操作时父窗口尺寸跟随变动

文章目录 概述无法resize到小尺寸可行方案其他方案 概述 本文旨在&#xff0c;实现如下所示的显示或隐藏 ‘附加选项’ 的效果&#xff0c;以折的不常用信息和操作项&#xff0c;减少普通用户负担&#xff0c;提升用户体验。在某些软件中此类窗口折叠效果&#xff0c;常用 “……

SpringCloud断路器

SpringCloud断路器 Hystrix 简介 hystrix对应的中文名字是“豪猪”&#xff0c;豪猪周身长满了刺&#xff0c;能保护自己不受天敌的伤害&#xff0c;代表了一种防御机制。 这与hystrix本身的功能不谋而合&#xff0c;因此Netflix团队将该框架命名为Hystrix&#xff0c;并使用…

2023最详细的接口测试用例设计教程,详细文档等你来拿

目录 一、接口测试流程 二、分析接口文档元素 三、如何设计接口测试用例 四、常用的接口测试用例覆盖方法 五、接口测试接口优先级 六、接口测试的设计思路分析 七、接口测试返回结果的比较 一、接口测试流程 1、需求讨论 2、需求评审 3、场景设计 4、数据准备 5、测试执…

sdf与timingCheck和后仿真

目录 1.Distributed delays 2.specify--endspecify 1.1 specify内部语法 2.sdf 2.1 sdf的格式 3.timingCheck和网表后仿真 4.关于负值delay sdf和 module 里面的specify--endspecify都可以对路径延时进行赋值和检查&#xff1b;HDL语言中的‘#()’也可以描述延时【叫做D…

没事千万别动生产服数据库 - 来自小菜鸟的忠告

阿里云官方参考文档 目录 背景一、环境部署二、目录规划三、操作步骤FAQ 背景 今天把一张 5500 多万条记录的表进行按年度拆分&#xff0c;本来打算将表数据拆分为 2020 年、2021 年、2022 年三张新表&#xff0c;提升原表查询效率&#xff0c;仅保留 2023 年数据。表拆分完毕…

【SpinalHDL快速入门】4.1、基本类型之Bool

Tips1&#xff1a; 由于SpinalHDL是基于Scala构建的&#xff0c;Scala本身自带类似变量Boolean&#xff0c;故在此要认准SpinalHDL中采用的是Bool而非Boolean&#xff1a; Bool&#xff08;大写的True和False&#xff09;&#xff1a;True表示1&#xff0c;False表示0Boolean&…

Vue3搭建

Vue3项目搭建全过程 vue create 项目名 选择手动吗&#xff0c;自定义安装 选择vue3 是否选择class风格组件 选择ts处理工具和css预处理器 Y 是否使用router的history模式 Y 选择css预处理语言 ;less 9.选择lint的检查规范 只使用EsLint官网推荐规范 使用EsLint官网推荐规…

MyBatis-plus(1)

基本概念: 一)开发效率也就是我们使用这款框架开发的速度快不快&#xff0c;是否简单好用易上手。从这个角度思考&#xff0c;每当我们需要编写一个SQL需求的时候&#xff0c;我们需要做几步 1)Mapper接口提供一个抽象方法 2)Mapper接口对应的映射配置文件提供对应的标签和SQL语…