动态规划

Dynamic programming

2017-06-19  本文已影响43人  __Jingyu__

本文针对两篇优秀动态规划文章中存在的不易理解的部分:状态、状态转移的定义和状态转移方程的编程实现部分进行个人解读。欢迎指出本文存在的错误和表述不清之处。

DP概述

DP(Dynamic Programming)是算法设计中解决最优化问题(eg: 最长公共子序列)的重要思想。
(待补充)
因此我们可以得出结论:

动态规划的本质,是对问题状态的定义和状态转移方程的定义。
——什么是动态规划?动态规划的意义是什么?(徐凯强 Andy的回答)

状态

这里给出我自己的一个定义后面会解释:

从“原始的最优化问题”剥离出的每个“最优化子问题”都是当前DP问题的一个状态,每个状态分布在“每次的决策前后”。

我们现在来看两个简单的动态规划问题:

问题1:
给定一个数列A,长度为N,
求这个数列的最长上升(递增)子数列(LIS)的长度.

1 7 2 8 3 4
为例。
这个数列的最长递增子数列是 1 2 3 4,长度为4;
次长的长度为3, 包括 1 7 8; 1 2 3 等.

剥离出的子问题,以及等价最终问题:
给定一个数列A,长度为N
设F(x):以数列A中第x项结尾的最长递增子序列的长度, 其中0 <= x <= N 。(子问题or状态)
求F(1)..F(N)中的最大值 (等价最终问题)

问题2:
如果我们有面值为1元、3元和5元的硬币若干枚,如何用最少的硬币凑够11元?

剥离出的子问题,以及等价最终问题:
如果我们有面值为1元、3元和5元的硬币若干枚
设D(i):凑够i元使用最少硬币个数,其中 0 <= i <= 11。(子问题or状态)
求D(11)的值。 (等价最终问题)

这两个问题便是“原始的最优化问题”。现在,根据“状态和状态转移方程的定义是动态规划的本质”的结论,我们需要做的就是从“原始的最优化问题”中找出状态,然后再得到状态转移方程,之后根据状态转移方程实现代码(其间还会使用到记忆和重叠子问题特性),最终得到解。

之所以把Fx叫做“状态”而不是“问题” ,一是因为避免跟原问题中“问题”混淆,二是因为这个新问题是数学化定义的。
——什么是动态规划?动态规划的意义是什么?(徐凯强 Andy的回答)

从前面对剥离子问题的分析大抵可以感受到这么一个过程: 整个DP问题从问题的定义边界开始(比如: 数列之长度为0,凑钱之总额为0),到问题收敛处为止(比如: 数列之长度为N,凑钱之总额为0),算法的每次决策都在推动前一个子问题发展到后一个子问题,往往这种推动都有多种可能性

比如:A={1 7 2 8 3 4},从当前F(3)={1,2}到F(6)时,我们可以很机智地选择从F(5) = {1,2,3}走最优解到F(6)={1,2,3,4}。但我们也可以任性地选择F(5)={1,2}到F(6)={1,2,4},或者F(5)={1,2,3},F(6)={1,2,3}..以及其他多种可能性)。此时我们可以在子问题之间以不同的状态(如F(5)={1,2,3} 或者F(5)={1,2})进行转移(比如从F(5)={1,2,3}到F(6)={1,2,3,4}),因此把子问题叫做“状态”,把子问题间的转移叫做“状态转移”是很形象的说辞。

状态转移方程

对状态的解释已经触及到了状态转移的概念:“子问题间通过决策进行推演的过程叫做状态转移”。所以,状态转移方程就应该是“子问题间通过决策定义的等式关系叫做状态转移方程”,通常状态转移方程和当前问题的边界条件联立起来叫做状态转移方程式。


——什么是动态规划?动态规划的意义是什么?(徐凯强 Andy的回答)


——动态规划:从新手到专家

显然,max(), min()就代表着一种最优决策。我们如果把max或者min去掉,那么上面的方程式依然可以叫做状态转移方程,只是得到的结果不一定是最优解了。

编程实现

初学者在解DP问题时,如何编程实现状态转移方程?如何在DP求解过程中利用重叠子问题进行记忆求解?
让我们看一下问题2的伪代码:


从伪代码我们可以分析出一个较为通用的DP代码实现过程:(S代表总额,N-1代表可能的硬币面值)

引用

什么是动态规划?动态规划的意义是什么?
http://www.hawstein.com/posts/dp-novice-to-advanced.html
动态规划:从新手到专家
https://www.zhihu.com/question/23995189

上一篇 下一篇

猜你喜欢

热点阅读