什么是动态规划

来源:互联网 发布:淘宝退货小纸条写什么 编辑:程序博客网 时间:2024/06/15 13:17

本文整理转载自:知乎什么是动态规划

什么是动态规划

动态规划(dynamic programming)与分治法相似,都是通过组合子问题的解来求解原问题,动态规划应用于子问题重叠的情况,即不同的子问题具有公共的子子问题。通常按照下面4个步骤来设计一个动态规划算法:
1. 刻画一个最优解的结构特征。
2. 递归地定义最优解的值
3. 计算最优解的值,通常采用自底向上的方法
4. 利用计算出的信息构造一个最优解
这是算法导论上的定义,但是这个定义对于初学者来说并没有很大的帮助,因为不知道如何划分子问题和刻画最优解的结构

1.动态规划的本质

动态规划的本质是对问题的状态的定义转态转移方程的定义
动态规划是通过拆分问题,定义问题状态和状态之间的关系,使得问题能够以递推(或者说分治)的方式去解决。但如何拆分问题才是动态规划的核心,而拆分问题靠的是状态的定义状态方程的定义

1.1 状态的定义

现举一个列子:

给定一个数列,长度为N,求这个数列的最长上升(递增)子数列(LIS)的长度.以 1 7 2 8 3 4为例。这个数列的最长递增子数列是 1 2 3 4,长度为4;次长的长度为3, 包括 1 7 8; 1 2 3 等.

要解决这个问题首先我们需要定义这个问题和这个问题的子问题。
所以我么重新定义这个问题

给定一个长度为N的数列。
Fk为:以数列中第k项结尾的最长递增子序列的长度.
F1...FN的最大值
很显然这个问题与原问题是等价的。
而对于Fk来说,F1 .. Fk1都是Fk的子问题:因为以第k项结尾的最长递增子序列(简称LIS),包含着以第1 … k 项结尾的LIS。
上述问题中Fk称之为状态,定义中的”Fk为数列中第k项结尾的LIS的长度”就叫做状态的定义。之所以把Fk叫做”状态”而不是”问题”,一是因为避免与原问题中”问题”混淆,二是因为这个新问题是数学化定义的。

当然,我们可以使用不同的视角来定义这个问题:
给定一个长度为N的数列,
Fi,k为:
在前i项中,长度为k的最长递增子序列中,最后一位的最小值。
1kN
若在前i项中,不存在长度为k的最长递增子序列,则Fi,k为正无穷。
求最大的x,使得FN,x不为正无穷。
这个问题的定义与原问题也是等价的。
上述的Fi,k就是状态,定义中的“Fi,k为:在前项中,长度为k 的最长递增子序列中,最后一位的最小值”就是对状态的定义。

1.2 什么是状态转移方程?

上述状态定义好之后,转态和转态之间的关系式,就叫做状态转移方程

对于LIS问题,第一种定义:
Fk为:以数列中第k项结尾的最长递增子序列的长度。
设A为题中数列,转态转移方程为:
F1=1 (根据定义导出边界情况)
Fk=max(Fi+1|Ak>Ai,i(1...k1)(k>1)
文字解释为:
以第k项结尾的LIS的长度是:保证第i项小的情况下,以第i项结尾的LIS长度加1的最大值,取遍i的所有值(i小于k).

第二种定义:
Fi,k为:在数列前i项中,长度为k的递增子序列中,最后一位的最小值
设A为题中数列,状态转移方程为:
Ai>Fi1,k1Fi,k=min(Ai,Fi1,k)
否则:Fi,k=Fi1,k

(边界情况需要分类讨论较多,在此不列出,需要根据状态定义导出边界情况。)大家套着定义读一下公式就可以了,应该不难理解,就是有点绕。

这里可以看出,这里的状态转移方程,就是定义了问题和子问题之间的关系。
可以看出,状态转移方程就是带有条件的递推式。

0 0
原创粉丝点击