动态规划

本质是什么? 解决重复运算 什么重复? 树形重复

DP三步走

  • 画出搜索树
  • 根据节点语义找出cache
  • 推导出状态转移方程

动态规划的中心思想是,面对 search tree 里都是 "overlap subproblem",如何根据问题结构制定缓存策略,避免重叠问题重复计算。

循环求解的方法 四个步骤

  1. 状态定义 state (相当于递归函数的传入参数和返回值的意义)
  2. 初始化, 从什么地方开始,哪些状态不是通过推导得来的,一眼看出来是什么值。
  3. 循环递推求解,怎么算
  4. 求结果,终点在哪

什么题极有可能是用DP:

Maximum/Minimum Yes/NO Count

最优方案

输入数据是有序的

什么情况不能用DP 求所有的具体方案 输入是一个集合而不是序列

关于贪心

极少有题是用贪心来求解,这种题很难出 难就难在你要证明贪心是对的。 大部分你能想到的贪心都是错的。Jump

分治法和动态规划的区别

分治法往下分的时候是不会分出同样的东西来的。比如二叉树

但是动归会有重复的子问题,才有空间换时间的可能性,需要记录中间的过程。

动归的思想是:大规模的问题是由小规模的问题的结果运算而来的。 什么是大规模的问题,就是问题的终点。 小规模的问题,是一眼就看出来结果的问题。

有循环依赖的情况,不能用动态规划。动态规划一般是有一个固定方向去前进的。

二维数组

网格类的题目 正方形用右下角作为定位角 长方形可以用左上角和右下角作为定位角。

例题:

Maximal Square

如何从五个for循环,优化到两层for循环的。

if (matrix[i][j] == 1)
f[i][j] = min(LEFT[i - 1][j], UP[i][j-1], f[i-1][j-1]) + 1; 

if (matrix[i][j] == 0)
f[i][j] = 0;

如何优化二维DP的空间

使用滚动数组

一个转移方程的是 f[i][j] = f[i - 1][j] + f[i][j - 1]

可以发现第i层和第i-2层没什么关系了,这种情况下 i-2 层可以重复利用。对第一维取模就可以了。 f[i % 2][j] = f[(i - 1) % 2][j] + f[i % 2][j - 1]

为什么不能对j取模?用上一行来推导下一行。

例题:

Longest Increasing Continuous subsequence II

Paint House

题意:没有两个相邻的房子是同样的颜色。

因为直到房子i,其最小的涂色开销是直到房子i-1的最小涂色开销,加上房子i本身的涂色开销。所以这道题使用dp来解。

但是房子i的涂色方式需要根据房子i-1的涂色方式来确定,所以我们对房子i-1要记录涂三种颜色分别不同的开销,这样房子i在涂色的时候,我们就知道三种颜色各自的最小开销是多少了。

空间上:我们在原数组上修改,可以做到不用空间。

Paint House II

和第一题思路差不多。但是由于有K种颜色,不能简单的用Math.min,我们可以遍历一遍找到除了自己以外最小的颜色。所以记录下最小的颜色和次小的颜色就可以了。

注意:维护的是最小的和次小的颜色。别忘了去更新次小的颜色。

results matching ""

    No results matching ""