【算法】动态规划dynamic programing

动态规划dynamic programing(能用动态规划或者迭代,就不用递归,因为递归太耗堆栈了,每一次函数调用都要在栈区创建一个空间,效率不高)

首先,动态规划问题的一般形式就是求最值。其实最准确的办法就是看题目中的给定的问题,这个问题能不能被分解为子问题,再根据子问题的解是否可以得出原问题的解。

求解动态规划的核心问题是穷举。因为要求最值,肯定要把所有可行的答案穷举出来,然后在其中找最值呗。但是,动态规划的穷举有点特别,因为这类问题存在重叠子问题,如果暴力穷举的话效率会极其低下,所以需要备忘录(一般使用一个数组充当这个备忘录,比如dp 数组的定义可以是当目标金额为 i 时,至少需要 dp[i] 枚硬币才能凑出目标金额),备忘录也叫做DP table(把「备忘录」作为一张表,这张表就叫做 DP table)来优化穷举过程,避免不必要的计算。另外,虽然动态规划的核心思想就是穷举求最值,但是问题可以千变万化,穷举所有可行解其实并不是一件容易的事,只有列出正确的状态转移方程才能正确地穷举。而且,动态规划问题一定会具备最优子结构,才能通过子问题的最值得到原问题的最值。 要符合最优子结构,子问题间必须互相独立,只要各子问题具有最优解,就能求出整个问题的最优解。最优子结构即原问题的解由子问题的最优解构成。如果想证明不符合最优子结构就用反证法,即如果不能利用子问题的最优解获得整个问题的最优解,那么这种问题就不具有最优子结构。

比如凑零钱问题,假设有两种面值的硬币 c[0]=5, c[1]=3,目标兑换金额为 k=11。原问题是求这种情况下求最少兑换的硬币数。如果你知道凑出 k=6 最少硬币数为 “2”(注意,这是一个子问题),那么你只需要再加 “1” 枚面值为 c[0]=5 的硬币就可以得到原问题的答案,即 2 + 1 = 3。
原问题并没有限定硬币数量,你应该可以看出这些子问题之间没有互相制约的情况,它们之间是互相独立的。因此,硬币找零问题满足最优子结构,可以使用动态规划思想来进行求解。

带备忘录的递归解法的效率已经和迭代的动态规划解法一样了。实际上,带备忘录的递归解法和迭代的动态规划已经差不多了,只不过带备忘录的递归解法叫做自顶向下(从上向下延伸,都是从一个规模较大的原问题向下逐渐分解规模,达到 base case,然后逐层返回答案),动态规划叫做自底向上(反过来,我们直接从最底下,最简单,问题规模最小的问题开始往上推,直到推到我们想要的问题的答案 ,这就是动态规划的思路,这也是为什么动态规划一般都脱离了递归,而是由循环迭代完成计算)

思考状态转移方程的框架

  1. 确定重叠子问题。或者叫最优子结构, 最优子结构即原问题(终止状态,这对原问题进行分解,对原问题的定义不一定必须是力扣题目中给的问题)的解由子问题(中间状态)的最优解构成。所以必须先明确 dp(i) 应该表示什么,这样才能利用dp(i)和 dp(i-1)的关系推出进行状态转移方程
  2. 思考状态转移方程,为啥叫「状态转移方程」?其实就是为了听起来高端。你把 f(n) 想做一个状态 n,这个状态 n 是由状态 n - 1 和状态 n - 2 相加转移而来,这就叫状态转移,仅此而已。
  3. 考虑边界问题(如初始状态),得出完整的动态转移方程

解决动态规划题目的钥匙也正是这个状态转移方程,其实状态转移方程直接代表着暴力解法(穷举)。千万不要看不起暴力解,动态规划问题最困难的就是写出这个暴力解,即状态转移方程。只要写出暴力解,优化方法无非是用备忘录或者 DP table,再无奥妙可言。
当然,如果你只推导出了状态转移方程基本上可以把动态规划题做出来了,但是往往很多人却做不对,这是为什么?这就得考虑边界问题。处理好边界问题我们就可以得到完整的状态转移方程了。

refer:
1.动态规划引入篇: 逐步探索找零问题
2.动态规划问题:零钱兑换的递归、备忘录、动态规划解法(Python)

案例分析

以一道题为例子去充分理解动态规划最基本的概念(三个要素就是初始状态,状态转移方程式和终止状态),题目中这个机器人只能向下和向右走,算他从左上角走到右下角有多少条路径。
在这里插入图片描述
方法:除了第一个格子的总路径次数(第一个格子的总路径次数为初始状态)以外,每一个格子的总路径数都应该是它上面的那个格子的总路径次数加上它左边的那个格子的总路径次数(方程式,也叫状态转移方程式)。那这个方程式一直加到什么时候为止呢?一直加到当r和c满足最后一个格子为止(这个格子的总路径次数就是终止状态)。中间的那些格子的总路径次数就都属于中间状态中间状态都要存下来!!!一般都是存到数组里去,不管是一维的还是二维的数组

在这里插入图片描述
再比如斐波那契数列用动态规划解就是如下图所示:
F(0)和F(1)就是初始状态,要求的F(n)就是终止状态,F(n)=F(n-1)+F(n-2)就是状态转移方程式。用数组将所有状态的值存起来,最终就能得到一个终止状态的值了。
在这里插入图片描述
动态规划算法能干些什么?
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值