动态规划用法总结(二)
动态规划是一个相对高级的工具,有些本身是动态规划的题可以用动态规划以外,当你无法一眼看穿最优解法时,你可以考虑直接使用动态规划。
动态规划最常见的解法思路步骤是
- 设计状态
- 设计转移方程
- 对转移方程时间空间优化
- 大多数可以改写为递推
- 边界处理
- 实现
优点是,基于状态和状态转移,空间复杂度时间复杂度在完全思考前容易预估计,状态一般与输入参数大小直接相关,容易设计,常见的贪心类的,堆栈类的有不少可以用动态规划实现。同时当实现完后,在优化过程中,可能可以推出最优解法。
当然伴随的缺点也是,可能比最优解法在时空复杂度会相对更高
技巧
- 一维状态转移
state[i] = f(state[i-1]);
- 一维状态多值转移
state[i] = f(state[i-1],...,state[i-k]);
- 一维状态常系数线性转移方程 改写为 矩阵乘法
state[i] = a1*state[i-1] + a2*state[i-2] ... + ak*state[i-k]);
- 多个一维状态转移
stateA[i] = f(stateA[i-1],...,stateA[i-j],stateB[i-1],...,stateB[i-k]);
stateB[i] = g(stateA[i-1],...,stateA[i-m],stateB[i-1],...,stateB[i-n]);
- 多维度状态转移
state[i][j] = f(state[i-1][j-1],state[i-1][j],state[i][j-1],...);
- 多维度一维转换
state[i*MAXJ+j] = stateold[i][j];
练手题目
题目6
这道题可以用技巧4, 多个一维状态分别记录, 正数最小绝对值和负数最小绝对值
if(val[i] > 0)
statepos[i] = min(val[i], statepos[i-1]);
else if(val[i] < 0)
stateneg[i] = max(val[i], stateneg[i-1]);
题目7
这道题可以用技巧1, 每次选取中心后, 当前长度是否是回文串与上一次相关
state[len] = state[len-1] && s[center + len + 0..1] == s[center-len]
题目8
这道题可以用技巧2, 设置状态为金额所需要的个数
state[i] = min(state[i],state[i-coin] + 1);
题目9
这道题可以使用技巧2, 建立当前值与在它前面比它小的值的长度关系
state[lower_bound(state.begin(),state.end(),v)] = v;
题目10
这道题可以使用技巧5, 记录两个字符串之间匹配的位置的最长长度.
state[i][j] = max(state[i-1][j],state[i][j-1], s1[i] == s2[j] && (state[i-1][j-1]+1))