动态规划(dynamic programming)

动态规划的基本思想算法

动态规划的基本思想在于发现和定义问题中的子问题,这里子问题可也以叫作状态;以及一个子问题到下一个子问题之间 是如何转化的 也就是状态转移方程数组

所以咱们遇到一个问题的时候 应该想想这个问题是否能用某种方式表示成一个小问题,而且小问题具备最优子结构spa

最优子结构:问题的最优解由相关子问题的最优解组合而成,这些子问题能够独立求解orm

关于最优子结构 咱们来看2个示例blog

一、求无权有向图中q-t的最短路径递归

若是q-t间的最短路径通过了点w  那么咱们能够证实 q-w  w-t也均是最短路径  字符串

因此无权有向图最短路径是具备最优子结构的it

二、求无权有向图中q-t的最长的路径im

NewImage

而无权有向图最长路径中 总结

q-t的最长路径是是q-r-t 但 q-r缺不是q-r的最长路径  q-s-t-r是一条更长的路径

因此无权有向图最长路径不具备最优子结构

 

二、关于动态规划的另外一个要点即是思考稍小的子问题和下一个子问题间是如何转化的也就是如何定义状态转移方程

状态转移方程的定义和咱们是如何定义子问题的有关

好比:求最长连续回文串:   给出一个字符串S,求最长的连续回文串,例如串 babcbabcbaccba 最长回文是:abcbabcba

咱们若是定义

p( i ) :以i结尾的最长回文串  咱们会发现咱们用子问题没法表示出p(i+1)

 

咱们从新考虑一下原问题  最长连续回文串  若是用另外一种方式来从新定义这个问题

已知字符串 S[0,n]   求回文传S[i,j]中最长的那一个

咱们能够定义如下子问题

P(i,j) : S[i,j] 是不是一个回文, P(i,i) = true

那么咱们能够定义以下的状态转换方程

P(i,j) ={ (P(i+1,j-1) && (Si == Sj) }



 

总结起来咱们能够用如下步骤去考虑一个问题如何用动态规划来解决

一、思考问题的最后一个步骤 是如何经过选择构造获得最终答案的

二、根据构造状况来发现子问题

三、看看可否肯定状态转移方程

 

 

 

 

动态规划与贪心等其余算法的比较

动态规划与分治,减治

分治       :将大问题分红若干个小问题去解决 递归的求解每一个小问题,每一个小问题之间没有关系  例如 快排

减治       :将大问题缩减成小问题,减掉的部分不须要考虑,例如:二分查找

动态规划:将原问题分红多个子问题,不一样子问题间存在必定的联系,相互间有重叠的子问题

这里我我的认为动态规划分治 减治都是将大问题拆分红小问题 进行求解 区别在于

减治法减掉的部分 能够不用再求解了;

分治法每一个小问题都须要进行求解;

动态规划不一样的子问题间是有相互重叠的子问题的

 

 

 

动态规划与贪心

动态规划在于咱们求解了全部子问题  虽然有些子问题最终并不能组成答案

而贪心算法任务无需求解全部子问题,因此选择在当前状况下最优的状况自顶向下的求解问题,贪心能够认为是动态规划的一个特例

若是用一个树来表示子问题的话 能够认为动态规划考虑了树中的全部节点

而贪心算法减去了树了许多枝干,在考虑了通向最优解的那一条路

 

 

常见的能够用动态规划解决的问题

一、最大连续子序列和: 

给定k个整数的序列{N1,N2,...,Nk },其任意连续子序列可表示为{ Ni, Ni+1, ..., Nj },其中 1 <= i <= j <= k。最大连续子序列是全部连续子序中元素和最大的一个,

例如给定序列{ -2, 11, -4, 13, -5, -2 },其最大连续子序列为{11,-4,13},最大连续子序列和即为20。

 

 

二、最大连续子序列乘积:

给一个浮点数序列,取最大乘积连续子串的值,例如 -2.5,4,0,3,0.5,8,-1,则取出的最大乘积连续子串为3,0.5,8。也就是说,上述数组中,3 0.5 8这3个数的乘积30.58=12是最大的,并且是连续的。

 

 

三、求最长连续回文串:   

给出一个字符串S,求最长的连续回文串,例如串 babcbabcbaccba 最长回文是:abcbabcba

 

四、字符串类似度:

 

把两个字符串变成相同的基本操做定义以下:
1.     修改一个字符(如把 a 变成 b)
2.     增长一个字符 (如 abed 变成 abedd)
3.     删除一个字符(如 jackbllog 变成 jackblog)
针对于 jackbllog到jackblog 只须要删除一个或增长一个 l 就能够把两个字符串变为相同。把这种操做须要的次数定义为两个字符串的距离 L, 则类似度定义为1/(L+1) 即距离加一的倒数。那么jackbllog和jackblog的类似度为 1/1+1=1/2=0.5 也就是所两个字符串的类似度是 0.5。
给定任意两个字符串,你是否写出一个是否来计算出它们的相识度。

 

 

五、最长公共子序列

对于序列S和T,求它们的最长公共子序列。例如X={A,B,C,B,D,A,B},Y={B,D,C,A,B,A}则它们的lcs是{B,C,B,A}和{B,D,A,B}。求出一个便可。

 

 

针对最大连续子序列乘积给出一段讲解与代码

最大连续子序列和:

给定k个整数的序列{N1,N2,...,Nk },其任意连续子序列可表示为{ Ni, Ni+1, ..., Nj },其中 1 <= i <= j <= k。最大连续子序列是全部连续子序中元素和最大的一个,

例如给定序列【-2, 11, -4, 13, -5, -2】,其最大连续子序列为{11,-4,13},最大连续子序列和即为20。

 

思路:

20这个答案 是咱们比较了【-2】,【11】,【-4】,【-2,11,-4,11】,【11,-4,13】,【11,-4,13,-5】,【11,-4,13,-5。-2】这几个序列以后获得

因此咱们定义子问题是

Max(i) : 以i结尾的连续序列的最大和

 

状态转移方程是:

Max[i] = max{a[i], Max[i-1] + a[i])

代码以下: 

int maxSubArray(int A[], int n) {
      int ans=A[0],i,j,sum=0;
      for(i=0;i<n;i++){
           sum+=A[i];
           ans=max(sum,ans);
           sum=max(sum,0);
   }
   return ans;
}

相关文章
相关标签/搜索