动态规划概述
Posted jason66661010
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了动态规划概述相关的知识,希望对你有一定的参考价值。
如果各个子问题不是独立的,不同的子问题的个数只是多项式量级,如果我们能够保存已经解决的子问题的答案
,而在需要的时候再找出已求得的答案,这样就可以避免大量的重复计算
。由此而来的基本思路是,用一个表记录所有已解决的子问题的答案,不管该问题以后是否被用到,只要它被计算过,就将其结果填入表中。
-
-
递归地定义最优值。
-
以自底向上的方式计算出最优值。
-
动态规划问题的特征
1、最优子结构
:当问题的最优解包含了其子问题的最优解时,称该问题具有最优子结构性质。
2、重叠子问题
:在用递归算法自顶向下解问题时,每次产生的子问题并不总是新问题,有些子问题被反复计算多次。动态规划算法正是利用了这种子问题的重叠性质,对每一个子问题只解一次,而后将其解保存在一个表格中,在以后尽可能多地利用这些子问题的解。
动态规划的形式
递推
记忆化搜索
状态与状态转移
最优化原理与最优子结构
决策与无后效性
例题:
老王想在未来的n年内每年都持有电脑,m(y, z)表示第y年到第z年的电脑维护费用,其中y的范围为[1, n],z的范围为[y, n],c表示买一台新的电脑的固定费用。 给定矩阵m,固定费用c,求在未来n年都有电脑的最少花费。 考虑第 i 年是否要换电脑,换和不换是不一样的决策,那么我们定义一个二元组(a, b),其中 a < b,它表示了第a年和第b年都要换电脑(第a年和第b年之间不再换电脑),如果假设我们到第a年为止换电脑的最优方案已经确定,那么第a年以前如何换电脑的一些列步骤变得不再重要,因为它并不会影响第b年的情况,这就是无后效性。 更加具体得,令d[i]表示在第i年买了一台电脑的最小花费(由于这台电脑能用多久不确定,所以第i年的维护费用暂时不计在这里面),如果上一次更换电脑的时间在第j年,那么第j年更换电脑到第i年之前的总开销就是c + m(j, i-1),于是有状态转移方程: d[i] = min{ d[j] + m(j, i-1) | 1 <= j < i } + c 这里的d[i]并不是最后问题的解,因为它漏算了第i年到第n年的维护费用,所以最后问题的答案: ans = min{ d[i] + m(i, n) | 1 <= i < n } 我们发现两个方程看起来很类似,其实是可以合并的,我们可以假设第n+1年必须换电脑,并且第n+1年换电脑的费用为0,那么整个阶段的状态转移方程就是: d[i] = min{ d[j] + m(j, i-1) | 1 <= j < i } + w(i) 其中w(i) = (i==n+1)?0:c; d[n+1]就是我们需要求的最小费用了。
动态规划的模型
线性模型
在一个夜黑风高的晚上,有n(n <= 50)个小朋友在桥的这边,现在他们需要过桥,但是由于桥很窄,每次只允许不大于两人通过,他们只有一个手电筒,所以每次过桥的两个人需要把手电筒带回来,i号小朋友过桥的时间为T[i],两个人过桥的总时间为二者中时间长者。问所有小朋友过桥的总时间最短是多少。 我们先将所有人按花费时间递增进行排序,假设前i个人过河花费的最少时间为opt[i],那么考虑前i-1个人过河的情况,即河这边还有1个人,河那边有i-1个人,并且这时候手电筒肯定在对岸,所以 opt[i] = opt[i-1] + a[1] + a[i] (让花费时间最少的人把手电筒送过来,然后和第i个人一起过河) 如果河这边还有两个人,一个是第i号,另外一个无所谓,河那边有i-2个人,并且手电筒肯定在对岸,所以 opt[i] = opt[i-2] + a[1] + a[i] + 2a[2] (让花费时间最少的人把电筒送过来,然后第i个人和另外一个人一起过河,由于花费时间最少的人在这边,所以下一次送手电筒过来的一定是花费次少的,送过来后花费最少的和花费次少的一起过河,解决问题) 所以 opt[i] = min{opt[i-1] + a[1] + a[i] , opt[i-2] + a[1] + a[i] + 2a[2] }
动态规划的简单使用
缓存与动态规划
例子:有一段楼梯有10级台阶,规定每一步只能跨一级或两级,要登上第10级台阶有几种不同的走法?
方法一:递归
1 int solution(int n){ 2 if(n>0 && n<=2) return n; 3 return solution(n-1) + solution(n-2); 4 }
方法二:DP记录避免重复计算数据
1 int dp[11]; 2 int solution(int n){ 3 if(n>0 && n<=2) return n; 4 if(dp[n]!=0) return dp[n]; 5 dp[n] = solution(n-1) + solution(n-2); 6 return dp[n]; 7 }
参考:https://blog.csdn.net/WhereIsHeroFrom/article/details/78922215
以上是关于动态规划概述的主要内容,如果未能解决你的问题,请参考以下文章
Mybatis -- 动态Sql概述动态Sql之<if>(包含<where>)动态Sql之<foreach>sql片段抽取