2020.1.20 主讲 GodofTheFallen
阶段的划分是人为的。但是必须满足在一个阶段的任意状态做出任何决策后,得到的新状态都属于之后的阶段。(甚至不能在原阶段停留)
不过实际问题中,有的时候阶段并不是线性的,有的时候你很难描述阶段,但是实际上阶段只是提供了一个解决问题的顺序和设计状态的思路,设计出合理高效的状态才是解决问题的关键。
即:阶段的最大作用是辅助状态设计。
决策是一个集合。不同的状态可能有不同的决策集合。但是同一个状态一定有相同的决策集合。
应描述一个事件,并且包含一切会对决策产生影响的限制条件
能动态规划解决的问题必须满足——任何一个子问题的最优解,做出第一步决策之后,剩下的决策集合仍然是转移到的子问题的最优解。这一条件叫做最优子结构。
这个条件也有等价描述如——
每个子问题的解与转移到它所经历的决策互不影响。(无后效性)
模板
int Solve(子问题)
{
if (子问题已求解) return 记录的结果;
枚举每一个可以转移来的子问题 Solve(这些子问题),更新当前答案;
记录答案;
return 答案;
}
//主程序中
枚举每一个子问题 Solve(该子问题);
用数组存答案,避免重复计算,每一个状态只用O(1)查询子问题的答案
优点:
缺点:
【DAG最大值】
递推比递归快
【乘积最大】
solve(n,k) = max {solve(i , k - 1)*num(i + 1 , n} 问题转化为 这个乘号之前的序列 添加k - 1个乘号的最大乘积子问题
dp的维数
状态的维数
需要的变量数,大多数情况下可认为是递推数组的维数 不过有时候比如f[i][j],i=1~n,j=0~1,则更倾向于1D而不是2D 转移的维数
递推式DP
优点:
缺点:
状态转移方程
$$f[U]=max/min{R(f[&cigema-1U],g(&cigema,cigema-1U))}`
状态转移方程
$$f[U]=max/min{R(f[&cigema-1U],g(&cigema,cigema-1U))}`
状态转移方程
$$f[U]=max/min{R(f[&cigema-1U],g(&cigema,cigema-1U))}`
原文:https://www.cnblogs.com/ZhengkunJia/p/12219154.html