动态规划解题套路

动态规划(Dynamic Programming)

动态规划属于运筹学范围。动态规划是求解决策过程最优化的数学方法。把多阶段过程转化为一系列单阶段问题,利用各阶段之间的关系,逐个求解,创立了解决这类过程优化问题的新方法——动态规划。

动态规划的问题之所以难,是因为它的其他算法不同,动态规划问题没有模板可以背诵。而且动态规划问题类型很多。总体来说,动态规划的问题有以下几类:

1、计数问题。典型题目有机器人走路。

2、求最大值最小值问题。典型问题有最长上升子序列。

3、存在性问题。典型问题有取石子游戏。

适用条件

动态规划问题必须满足以下的两个条件:

最优化原理

也就是最优子结构。一个最优化策略具有这样的性质,不论过去状态和决策如何,对前面的决策所形成的状态而言,余下的诸决策必须构成最优策略。简而言之,一个最优化策略的子策略总是最优的。一个问题满足最优化原理又称其具有最优子结构性质。

无后效性

将各阶段按照一定的次序排列好之后,对于某个给定的阶段状态,它以前各阶段的状态无法直接影响它未来的决策,而只能通过当前的这个状态。换句话说,每个状态都是过去历史的一个完整总结。这就是无后向性,又称为无后效性。

动态规划解题方法

1、自底向上

2、自顶向下


动态规划解题套路

动态规划解题可以分为 4 步:

第一步:确定状态。

第二步:状态转移方程。

第三步:初始条件和边界情况。

第四步:计算顺序。

下面我们使用一个简单的动态规划入门题来说明这四个步骤。

过程详解

问题描述:找零

我们有三种硬币,面值分别为:2 元、5 元和 7 元,而且每种硬币足够多。现在我们要购买一本价值为 27 元的书。如何用最小的硬币组合正好付清,而且不需要找零。

本题就是一个典型的求最大值最小值动态规划问题。

如果本题用贪心的方法,可以得到:先用 3 个 7 元,构成 21 元。剩下 6 元,再用 3 个 2 元构成。这样需要使用的硬币组合为:2+2+2+7+7+7=27,合计为 6 枚。

而正确的答案是:7+5+5+5+5=27,合计为 5 枚。

确定状态

状态是动态规划的核心。在动态规划解法中,我们都需要一个数组,数组可以是一维数组,可以是两维数组。数组的作用就是描述问题的状态。例如使用一维数组 dp[i] 表示第 i 步的状态,使用二维数组 dp[i][j] 表示第 i 步中第 j 部分状态。状态数组类似于我们描述数学问题中的未知量 x、y、z 等。

因此对于任何一个动态规划问题,我们首先需要确定状态。这里包含了两个子问题:

1、最后一步。虽然我们不能确定过程,但是每个问题都有最后的确定状态。

按例题找零为例,假设这个问题一定存在一个最优解,使用 K 枚硬币构成一个最优策略。

我们知道最后一步就是要将所有硬币组合总额编程 27。那么这 K 枚硬币可以描述为 A1,A2,...,AK,将这 K 枚硬币累加起来,可以得到a_{1}+a_{2}+\cdots +a_{K}=27,虽然我们不知道 Ai 的具体值。

那么最后一步就是这个最优策略中的最后一个决策,也就是最后一个硬币 A_{K}。扣除最后一个硬币后,前面所有硬币的总和将是 27-A_{K},如下图所示。

我们不需要关注前面 K-1 枚硬币是怎么样的组合,只需要保证拼出 27-A_{K} 即可。而且要保证拼出的硬币数量最小,也就是前面也是最优策略。这个很容易用反证法来证明。

2、子问题。

解决了最后一步(最少用多少枚硬币可以拼出 27-Ak)后,我们可以使用递归的思路,确定出子问题。这样,我们就将一个规模较大问题,分解为若干个问题一样规模较小子问题(Subproblem)。

这样,子问题就变成:最少用多少枚硬币可以拼出 X 元。

总结起来,就是通过描述最后一步,将一个规模大的问题,分解为若干个相同的而且规模较小的子问题。

状态转移方程

到目前为止,我们还是不知道最后一枚硬币 Ak 到底是多少。不要急。根据题目,我们知道硬币的可能只有 2 元、5 元和 7 元。那么最后一枚硬币也只能是这三种硬币中的一种。

这样,我们可以看出一个一维数组可以描述这个状态转移的过程。我们假设 dp[k] 表示拼出 K 元的最优策略,也就是 dp[1] 表示拼出 1 元的最优策略,dp[27] 表示拼出 27 元的最优策略。

因此,根据最后一步的描述,我们可以知道,要拼出 27 元,我们有三种可能:

1、使用 2 元拼出 27 元,对应的状态转移方程就是 dp[27]=dp[27-2]+1,也就是 dp[25] 加上一枚 2 元硬币。

2、使用 5 元拼出 27 元,对应的状态转移方程就是 dp[27]=dp[27-5]+1,也就是 dp[22] 加上一枚 5 元硬币。

3、使用 7 元拼出 27 元,对应的状态转移方程就是 dp[27]=dp[27-7]+1,也就是 dp[20] 加上一枚 7 元硬币。

除此之外,没有其他可能。题目要求我们求出最优策略,也就是最小的可能性,因此对应的 dp[27] 为取这三个方法的最小值,即dp[27]=min(dp[27-2], dp[27-5], dp[27-7])+1

这样,我们使用 dp[x] 表示最少硬币拼出 x 元的最优策略,我们可以得出整个问题的状态转移方程。

dp[x]=min(dp[x-2], dp[x-5], dp[x-7])+1

其实本问题就是使用自顶向下的方法来解决。

初始条件和边界情况

到这里为止,我们写出了题目的状态方程,下面我们需要确定该方程的初始条件和边界情况。

边界条件

y 元不能拼出,我们定义 dp[y] 为正无穷大。例如 dp[-1]=\infty。这样我们可以写出边界条件如下:

dp[x]=\infty , x<0

初始条件

从状态转移方程第递推式中,我们需要给出状态方程的初始条件。在状态方程中,我们可以看出只需要给出一个初值就可,也就是 dp[0]。对应的初始条件如下:

dp[0]=0

这样一个完整的状态转移方程,我们就可以写出如下所示:

dp[x]=min(dp[x-2], dp[x-5], dp[x-7])+1\\dp[0]=0\\dp[x]=\infty ,x<0

计算顺序

根据上面推导出的状态转移方程,我们可以非常容易知道,计算的顺序应该是 1、2、3、...、K。也就是使用一个 for 循环就可以解决问题。

这样,我们就可以非常轻松的解决这个例题。对于其他动态规划的题目,我们都可以通过同样的步骤来完成,只需要多加练习即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

努力的老周

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值