动态规划问题满足三大重要性质 最优子结构性质:如果问题的最优解所包含的子问题的解也是最优的,我们就称该问题具有最优子结构性质(即满足最优化原理)。最优子结构性质为动态规划算法解决问题提供了重要线索。 动态规划算法正是利用了这种子问题的重叠性质,对每一个子问题只计算一次,然后将其计算结果保存在一个表格中,当再次需要计算已经计算过的子问题时,只是在表格中简单地查看一下结果,从而获得较高的效率。
文章目录 一、动态规划场景 二、动态规划分类 1、坐标型动态规划 2、前缀划分型动态规划 3、前缀匹配型动态规划 4、区间型动态规划 5、背包型动态规划 一、动态规划场景 ---- 动态规划 动态规划使用场景 ---- 动态规划分类 : 坐标型 动态规划 , 又分为 一维坐标 动态规划 , 二维坐标 动态规划 ; 前缀型 动态规划 该类型动态规划有分为如下两种类型 ; 前缀划分型动态规划 前缀匹配型动态规划 背包型 动态规划 区间型 动态规划 不同类型的 动态规划 中 , 状态 值 的表示形式不同 , 将 动态规划 的 状态 表示形式 确定 , 该问题基本就可以解决 ; 1、坐标型动态规划 坐标型 动态规划 , 又分为 一维坐标 动态规划 , 二维坐标 动态规划 ; 一维坐标 动态规划 , 使用 一维数组 dp 表示状态 , dp[i] 表示 从 起点坐标位置 开始 到 坐标 i 位置 的 最大值 | 最小值 单词拆分 II : https://leetcode.cn/problems/word-break-ii/ 3、前缀匹配型动态规划 前缀划分型 动态规划 : 使用 二维数组 dp 表示状态 , dp[i
文章目录 一、动态规划四要素 1、动态规划状态 State 2、动态规划初始化 Initialize 3、动态规划方程 Function 4、动态规划答案 Answer 一、动态规划四要素 ---- 在上一篇博客 【算法】动态规划 ① ( 动态规划简介 | 自底向上的动态规划示例 | 自顶向下的动态规划示例 ) 中 , 不管是 自底向上的动态规划 还是 自顶向下的动态规划 , 实现 动态规划 算法时 ① ( 动态规划简介 | 自底向上的动态规划示例 | 自顶向下的动态规划示例 ) 中 , 动态规划 状态 State 就是 二维数组 dp , dp[i][j] 表示从 第 i 行 第 j 列的元素出发 ; 如 : 上一篇博客 【算法】动态规划 ① ( 动态规划简介 | 自底向上的动态规划示例 | 自顶向下的动态规划示例 ) 中 自顶向下的动态规划示例 中 , 对 数字三角形 左右两边 的 两列 数据进行初始化 操作 ; 3、动态规划方程 Function 动态规划 的 方程 Function , 与 递归的拆解 对应 ; 动规方程 主要用于 描述 大规模问题 如何 拆解成 小规模问题 , 即 大规模问题 是
文章目录 一、动态规划特点 1、求解类型 2、方向性 3、动态规划状态选择 4、动态规划方程设计 一、动态规划特点 ---- 1、求解类型 求解类型 : 动态规划 必须是求 最值 , 可行性 , 方案数 , 三者之一 , 如果求其它内容 , 则不能使用动态规划算法 ; 求最值 : 最大值 , 最小值 等 ; 大规模问题的结果 由 小规模问题 的计算结果 取最大值 大规模问题的结果 由 小规模问题 , 在该问题中 , 我们将其行走方向 固定在了右侧的四个方向 , 这样就不会出现循环依赖 ; 如 : 数字三角形 , 在三角形中 , 只能 从上向下走 , 不能向上走 , 这样避免循环依赖 ; 3、 动态规划状态选择 动态规划状态选择 : 在 坐标型 动态规划中 , 直接使用 坐标的下标 来标记 相同位置的 状态 ; 状态数组中存储的元素是 : 最大值 | 最小值 方案数 可行性 4、动态规划方程设计 动态规划方程设计 : 动态规划方程 , 最主要的作用是 体现出 下一步坐标状态 与 上一步坐标状态 之间的联系 ; 也就是 大规模问题解决方案 ( 下一步坐标状态 ) 与 小规模问题解决方案 ( 上一步坐标状态
例如,上图是一个7 x 3 的网格。有多少可能的路径? 根据题目,可以知道当网格为1 x N或者N x 1的时候,路径都是一种。
示例 1: 输入:m = 3, n = 7 输出:28 示例 2: 输入:m = 3, n = 2 输出:3 解释: 从左上角开始,总共有 3 条路径可以到达右下角。 向右 -> 向下 -> 向下 向下 -> 向下 -> 向右 向下 -> 向右 -> 向下 示例 3: 输入:m = 7, n = 3 输出:28 示例 4: 输入:m = 3, n = 3 输出 :6 提示: 1 <= m, n <= 100 题目数据保证答案小于等于 2 * 109 题解 简单动态规划即可 class Solution { public: int uniquePaths
F(5) / \ F(4) F(3) 本题目的DP Table是一维的,所以称之为一维动态规划。 动态规划和分治 两者的区别在于:动态规划的下一个子阶段的求解是建立在上一个子阶段的解的基础上,进行进一步的求解。 动态规划和贪心 贪心算法每走一步都是不可撤回的,而动态规划是在一个问题的多种策略中寻找最优策略,所以动态规划中前一种策略可能会被后一种策略推翻。 Subarray Best Time to Buy and Sell Stock 二维动态规划
动态规划有时被称为递归的相反的技术。递归是从顶部开始将问题分解,通过解决所有分解小问题的方式,来解决整个问题。 而动态规划这是从底部开始解决问题,将所有小问题解决掉,然后合并成整体的解决方案,从而解决掉整个大问题。 动态规划方案通常使用一个数组来建立一张表,用于存放被分解成众多子问题的解。当算法执行完毕,最终的解法将会在这个表中找到。 if(n < 2){ return n; }else{ return fib(n - 1) + fib(n - 2); } } 动态规划解法 ,给定两个字符串,求出它们的最长公共字串 我们回顾一下动态规划的解题思路: 从底部开始解决问题,将所有小问题解决掉,然后合并成一个整体的解决方案。
动态规划,就是找问题子问题,并且建立关系,如何找出有用的子问题,很关键 1、1,3,5面值硬币,求n元,至少需要几枚硬币组合,比如100元, 如果当前1元,99元至少需要多少 如果当前3元,97元至少需要多少 如果当前5元,95元至少需要多少 只要求出三种情况,最小即为所求,递推关系 d[i] = min(d[i-1]+1, d[i-3]+1, d[i-5]+1), i >= 5 def get_coin (coins, n): # 假设i元需要j枚硬币d[i]=j,d[0]=0,d[1]=1 # d[i]=min{d[i-1]+1,d[i-3]+1,d[i-5]+1} # coins >=A[2],A[3]>=A[1],d[2]=max{d[1]+1,d[2]+1} # A[i]与前面进行比较,求的最大值 d = [1]*len(numbers) n = len ], [9,3,5,7], [1,4,3,8]] # M 行, N列 M = len(apple) N = len(apple[0]) A = [[0 for i in range(N)] for i
步骤设计: 1 找出最优解的性质,并刻画其结构特征 2 递归地定义最优值 3 以自底向上的方式计算出最优值 4 根据计算最优值得到的信息,构造最优解 应用实例: 矩阵连乘问题 最长公共子序列 最大子段和
参考 : 代码随想录 理论知识 动态规划问题,将拆解为如下五步曲,这五步都搞清楚了,才能说把动态规划真的掌握了! */ public class beibao { public static void main(String[] args) { int[] weight = {1,3,4} int bagSize = 4; testWeightBagProblem(weight,value,bagSize); } /** * 动态规划获得结果 * 那么dp[i - 1][j - weight[i]] + value[i] (物品i的价值),就是背包放物品i得到的最大价值 */ //todo 3. 确定递推公式 //dp[j] = max(dp[j],dp[j - weight[i]]) //todo 3.
动态规划一般来说和分治有点类似都是让他们去处理相同的子问题,但是在动态规划里面你会遇到更多的相同子问题。 然后我们就会导致很多的重复计算,所以一般我们可以使用递归来完成一个动态规划要完成的任务,但是这样一般会重复计算很多东西,所以动态规划一般就增加了一些矩阵来存放上一次计算的结果。
一、介绍动态规划是什么算法,顾名思义就是动态地进行计算,下面来看看百度词条的解释动态规划(Dynamic Programming,DP)是运筹学的一个分支,是求解决策过程最优化的过程。 20世纪50年代初,美国数学家贝尔曼(R.Bellman)等人在研究多阶段决策过程的优化问题时,提出了著名的最优化原理,从而创立了动态规划。 动态规划的应用极其广泛,包括工程技术、经济、工业生产、军事以及自动化控制等领域,并在背包问题、生产经营问题、资金管理问题、资源分配问题、最短路径问题和复杂系统可靠性问题等中取得了显著的效果 。 以上是动态规划算法的解释,那么如何将应用到实际问题中呢或者说该算法的核心是什么,我们将采用何种思维去使用这个算法,进行破题它的核心就是将问题分解为一系列子问题,并通过记忆化或递推的方式求解子问题,从而得到原始问题的解 三、最后大家可以多去力扣看看动态规划的具体问题,上面只是一个简单的示例,实际的动态规划问题可能会更复杂。
动态规划(dynamic programming)是求解决策过程(decision process)最优化的数学方法。 炮兵布阵等; 树形动规:贪吃的九头龙,二分查找树,聚会的欢乐,数字三角形等; 背包问题:01背包问题,完全背包问题,分组背包问题,二维背包,装箱问题,挤牛奶(同济ACM第1132题)等; 动态规划的特点 并将其结果保存在一个表中,以后用到的时候直接取 ------自底向上地计算(分治法自顶向下,没有考虑子问题重叠) 适用范围: ------优化问题:可分为多个相关子问题,子问题的解被重复使用 使用动态规划的条件 ------优化子结构(保证动态规划的正确性):当一个问题的优化解包含了子问题的优化解时,我们说这个问题具有优化子结构。 ,并获取构造最优解的信息 ------根据构造最优解的信息构造优化解 动态规划的核心是状态和状态转移方程。
动态规划 ---- 动态规划常常适用于有重叠子问题和最优子结构性质的问题,动态规划方法所耗时间往往远少于朴素解法。 动态规划往往用于优化递归问题,例如斐波那契数列,如果运用递归的方式来求解会重复计算很多相同的子问题,利用动态规划的思想可以减少计算量。 动态规划法仅仅解决每个子问题一次,具有天然剪枝的功能,从而减少计算量, 一旦某个给定子问题的解已经算出,则将其记忆化存储,以便下次需要同一个子问题解之时直接查表。 动态规划模板步骤: 确定动态规划状态 写出状态转移方程(画出状态转移表) 考虑初始化条件 考虑输出状态 考虑对时间,空间复杂度的优化(Bonus) 算法应用 ---- Leetcode 比如[1,3,5 ]元素3 从1递增到3 递增元素个数是2,dp[1]=2 初始化 dp=[1]*n 后比较 代码 class Solution: def findLengthOfLCIS(
接下来 m 行,每行有 3 个正整数,x,y,z,每两个整数之间用一个空格隔开。 数据范围 1≤n≤100000, 1≤m≤500000, 1≤各城市水晶球价格≤100 输入样例: 5 5 4 3 5 6 1 1 2 1 1 4 1 2 3 2 3 5 1 4 5 2 输出样例 : 5 题解 环形动态规划最短路,所有方案可以按照中间节点来划分,dmin[i]:代表节点i之前节点的所有最小值,dmax[i]:代表节点i之后所有节点的最大值,由于是环形的动态规划,所以要用spfa rhead[N],cnt,rcnt; int a[N]; int n,m; int vis[N],q[N],hh,tt; int dmin[N],dmax[N]; const int INF = 0x3f3f3f3f
文章目录 一、动态规划简介 二、自底向上的动态规划示例 1、原理分析 2、算法设计 3、代码示例 三、自顶向下的动态规划示例 1、算法设计 2、代码示例 一、动态规划简介 ---- 动态规划 , , 没有具体的步骤 , 只有一个核心思想 ; 动态规划 的 核心思想 是 由大化小 , 大规模问题 使用 小规模问题 计算结果 解决 , 类似于 分治算法 ; 动态规划 与 贪心算法 区别 : 动态规划 ; 动态规划 实现方法 : 递归 : 如 记忆化搜索 的实现 ; for 循环 : 使用 多重 for 循环 实现 ; 二、自底向上的动态规划示例 ---- 从 下图的 数字三角形 中 从上到下 找到一条 最短路径 ; 1、原理分析 自底向上 的动态规划思想 : 下面的 n 的最佳路径 指的是 以 n 为起点 到达 最底层的 的最短路径 ; 顶部的 1 的最佳路径 依赖于 2 和 3 中的 最佳路径 , 最短路径为 2 + 3 = 5 3 的最短路径 从 -5 和 6 之间取最短的最短路径 , 是 -5 , 对应最短路径 3 , 最短路径为 3 + 3 = 6 倒数第四排 ( 第一排 ) : 1 的
经过询问才知道,罗拉面试挂在了动态规划。 说到动态规划,八哥可就来精神了,于是就结合劳拉的面试题简单的和她介绍了动态规划。 这种自底向上方式就是动态规划。 这样的话动态规划有什么优势呢? 年轻人别急嘛,动态规划没那么简单,当然掌握核心思想也不难。 我这只是举个例子,其实斐波那契数列没必要用动态规划,只是这个例子比较简单而已,刚好可以用来入门。 动态规划也不是用于解决这类问题的。 动态规划通常用来求解最优化问题,一般此类问题有很多的解,我们希望找到一个最优的解(比如最大值、最小值)。 image.png 怎样,没头绪了吧,别急用动态规划就很容易做这类题目,至于怎么做,且听下回分解。
示例 2: 输入: "226" 输出: 3 解释: 它可以解码为 "BZ" (2 26), "VF" (22 6), 或者 "BBF" (2 2 6) 。 i-1]不为零即可,从而需要加上前i-2的解码数量,即dp[i] += dp[i-1] 由两个数字编码而来, 即最后一个数字s[i-2]和s[i-1]构成的两位数字在1~26之间,从而要加上前i-3个数字的解码数量 你可以对一个单词进行如下三种操作: 插入一个字符 删除一个字符 替换一个字符 示例 1: 输入: word1 = "horse", word2 = "ros" 输出: 3 解释: horse -> rorse (将 'h' 替换为 'r') rorse -> rose (删除 'r') rose -> ros (删除 'e') 解题思路: 利用动态规划的思想,我们可以得到以下几个递推式: 在DP矩阵初始化时
根据动态规划的五步解题思路: 3.代码 具体代码如下(C++): class Solution { public: int minFallingPathSum(vector<vector< 根据动态规划的五步解题思路: 3.代码 具体代码如下(C++): class Solution { public: int minPathSum(vector<vector<int>>& 2.解题思路 这道题要求按摩师最大工作分钟数,可以计算每一个预约中按摩师接不接该预约的最大分钟数,然后最终计算所有的预约最大分钟数(根据具体情况,有时候不接当前预约反而可以获得更大的工作时间) 根据动态规划的五步解题思路 : 3.代码 具体代码如下(C++): class Solution { public: int massage(vector<int>& nums) { if(nums.size } return max(dp[nums.size() - 1][0], dp[nums.size() - 1][1]); } }; 4.运行结果 总结 今天是算法练习的第3天