Dynamic Programming: intermediate result are “cached" for future calls

什么情况下可能动态规划

  • 最大值最小值/是否可行/方案总数

什么情况不用动态规划

  • 求所有方案/集合而不是序列求所有方案基本都是用recursion/DFS
  • 输入数据是集合而不是序列
  • 暴力算法复杂度已经是多项式级别
    • DP擅长优化指数级别复杂度(2^n, n!)到多项式级别复杂度(n^2, n^3)
    • 不擅长优化n^3到n^2

解决动态规划问题的四点要素:

  • 状态: 存储小规模问题的结果
  • 方程: 状态之间的联系,怎么通过小的状态,来算大的状态
  • 初始化: 最极限的小状态是什么, 起点
  • 答案: 最大的那个状态是什么,终点

三种面试常见的动态规划类别及状态特点

坐标,单序列,双序列

一些奇技淫巧

  • 初始化第0行和第0列(不能通过递归方程得到的状态需要初始化)
  • n个数开n+1个位置的数组
  • 二维网格类题目小技巧: 正方形用右下角作为定位角(A[i][j]+边长)
    长方形用左上角和右下角做定位角

空间优化:滚动数组

一维:需要存储的状态为2个的情况下
f[i] = max(f[i-1], f[i-2]+A[i])装化为 f[i%2] = max(f[(i-1)%2], f[(i-2)%2])
二维:f[i][j]由f[i-1]行决定于之前行无关,即f[i%2][j]由f[(i-1)%2]行来决定

动归实现方式:

a) 循环:从小到大递推
b) 记忆化搜索:从大到小(画搜索树帮助确定状态,并剪支)
什么时候用记忆化搜索:

  1. 状态转移麻烦,不是顺序
  2. 初始化状态难以找到

博弈类DP: 有先手后手

state: 定义一个人的状态,通常是先手
function: 考虑两人的状态做更新
initializ: 根据最初几步操作进行初始化
answer:

区间类DP(一般都是O(n^2))

  • 求一段区间[0, n-1]的解min/max/count
  • 转移方程通过区间更新
  • 从大到小更新(逆向思维)

背包类DP

  • 用值作为DP维度
  • DP过程就是填写矩阵
  • 可以滚动数组优化

results matching ""

    No results matching ""