首先声明!鉴于之前有一段时间经常有朋友问我一些DP的问题,趁着现在有点时间,我在网上找了很多关于DP的资料,也希望大家可以通过这篇文章有一些收获!
引入问题:现在我有1块,3块,5块的硬币,假设我要凑成n块,那么我要怎么凑硬币,才能够保证凑成n块钱,并且硬币数目是最少的?
对于没有DP概念的读者们来说,第一想到的办法要么是贪心法(暴力破解),要么就是回溯法。但是使用贪心法每次达到局部最优解,但是出现的后果是可能求不出结果。why?
只要我将问题中的1块钱改成2块钱,将n块钱量化成9块钱,那么使用贪心法的读者就已经无法求出答案了。使用贪心法无法求解的最大原因
(1)贪心策略是由上一步的最优解推导下一步的最优解,而上一部之前的最优解则不作保留
(2)贪心法正确的条件是:每一步的最优解一定包含上一步的最优解
回溯法是可以求解这个问题,但是他的时间复杂度会比动态规划大很多,而且多了很多没有必要的运算步骤。
那么,动态规划应运而生!通过每次的最优决策,记录每一次的状态的变化,从而达到整体上的最优。对于硬币问题的动态规划求解,我将会在硬币问题文章中进行全面分析!欢迎读者观看。
对于初学者,对于动态规划肯定有很多疑惑,疑惑主要归结为下面几点。
动态规划算法:
(1)、全局最优解中一定包含某个局部最优解,但不一定包含前一个局部最优解,因此需要记录之前的所有最优解;
(2)、动态规划的关键是状态转移方程,即如何由以求出的局部最优解来推导全局最优解;
(3)、边界条件:即最简单的,可以直接得出的局部最优解。
第一:什么是动态规划(dynamic programming)?
动态规划(dynamic programming)是运筹学的一个分支,是求解决策过程(decision process)最优化的数学方法。20世纪50年代初美国数学家R.E.Bellman等人在研究多阶段决策过程(multistep decision process)的优化问题时,提出了著名的最优化原理(principle of optimality),把多阶段过程转化为一系列单阶段问题,利用各阶段之间的关系,逐个求解,创立了解决这类过程优化问题的新方法——动态规划。1957年出版了他的名著《Dynamic Programming》,这是该领域的第一本著作。(注:引用百度百科关于动态规划的概念解释)
第二:动态规划的用途是什么?
动态规划问世以来,在经济管理、生产调度、工程技术和最优控制等方面得到了广泛的应用。例如最短路线、库存管理、资源分配、设备更新、排序、装载等问题,用动态规划方法比用其它方法求解更为方便。
动态规划主要用于求解以时间划分阶段的动态过程的优化问题,但是一些与时间无关的静态规划(如线性规划、非线性规划),只要人为地引进时间因素,把它视为多阶段决策过程,也可以用动态规划方法方便地求解。
通过使用动态规划解决的相关问题:
线性动规:拦截导弹,合唱队形,挖地雷,建学校,剑客决斗等;
区域动规:石子合并,加分二叉树,统计单词个数,炮兵布阵等;
树形动规:贪吃的九头龙,二分查找树,聚会的欢乐,数字三角形等;
背包问题:01背包问题,完全背包问题,分组背包问题,二维背包,装箱问题,挤牛奶(同济ACM第1132题)等;
第三:如何使用动态规划?
对于分析问题是否应该使用动态规划,首先要满足以下的条件
(1)、最优化原理:如果问题的最优解所包含的子问题的解也是最优的,就称该问题具有最优子结构,即满足最优化原理;
(2)、无后效性:即某阶段状态一旦确定,就不受这个状态以后决策的影响。也就是说,某状态以后的过程不会影响以前的状态,只与当前状态有关;
(3)、有重叠子问题:即子问题之间是不独立的,一个子问题在下一阶段决策中可能被多次使用到(该性质并不是动态规划适用的必要条件,但是如果没有这条性质,动态规划算法同其他算法相比就不具备优势)。
动态规划的本质,就是对问题状态的定义和状态转移方程的定义。
定义
从第一阶段S1开始到最后阶段Sn状态为止,将每个阶段的决策uk(Sk)( k=1,2,…,n)连接起来所构成的决策序列称为策略或全策略,记为
P1,n(S1)={u1(S1),u2(S2)…uk(Sk)…un(Sn)}
如果不是从S1状态开始,而是从第k阶段的Sk状态开始,至最后阶段Sn状态为止,则将由Sk状态开始至Sn状态为止的策略序列称为后部子策略,记为
Pk,n(Sk)={uk(Sk),uk+1(Sk+1)……un(Sn)}
可见,它是策略P1,n(S1)的一个子策略,且是后部的子策略。
状态转移方程
由于系统处于Sk状态,通过决策uk(Sk),进入Sk+1状态,描述系统由Sk状态向Sk+1状态转移的方程叫状态转移方程,显然有
Sk+1=T(Sk,uk)
(由于每个动态规划的策略都有小差别,所以状态转移方程无法具体,只能有一个抽象的公式)