动态规划问题总结【学习中】

子串:连续的

子序列:不需要连续

DP总览

标准问法

计数(多少种路径...)

  • Li114,多少种路径
  • 多少种方法选出k个数,使得和是sum

最值(最大利润、最小数量、最长子串...)

  • Li669,硬币的最少个数
  • Li076,最长上升子序列

存在性(可行性、能否)

  • Li116,能否跳到最后一块石头

问题特点

  1. 可以变成子问题(最优子结构)
  2. 子问题之间存在重复计算

解题步骤

  1. 确定状态

    • 考虑最后一步(最后一个物品,最后一个路径,最后一个部分)
    • 变成解决子问题了(规模更小的问题)
    • 状态就是计算大问题时必要的子问题的信息
  2. 确定状态转移方程

    • dp[i] 和 f(i) 不完全一样 P2O_2e 14Li515
    • dp[i]的计算顺序(从大到小还是从小到达)有影响 0-1背包
  3. 处理初始条件边界情况

    • 初始条件:开始的几项(用不了转移方程求解的就是初始条件)
    • 边界情况:
      • 数组下标越界时
      • 情况不存在时的dp值(比如股票问题的负无穷)

注意计算dp的顺序

  • 原则就是计算需要的数据都是之前计算的结果,以及别覆盖还要用的数据(压缩空间时注意)
  • 一般都是从小到大,背包问题的空间优化必须反向计算

空间优化

  • 使用滚动数组, 根据状态转移方程中需要的最旧的数据确定大小
  • 先写出不压缩的,然后用dp[i % n]代替dp[i]是最方便, 最好理解的解决办法, 其中n是压缩后的数组大小。用个变量名cur = i % n更容易修改
  • 一般是逐行扫描, 滚动数组长度是列数的倍数。 如果列多行少时, 可以考虑逐列扫描让滚动数组长度是列数的倍数, 进一步优化空间

坐标型20%

问题特点

  1. 条件: 一般给矩阵
  2. 状态定义 : 状态dp[i]的含义是以a[i]结尾的序列的性质
  3. 转移方程 : /
  4. 返回 : 最后返回dp[n - 1]

刷题记录

Leet Lintcode 简介 TO SO 收获
L62 Li114 不同路径
L63 Li115 不同路径,网格中有障碍
L64 Li110 路径上数字和的最小值
Lv361 Li553 炸弹袭击 1. 分解成4个方向,分别记录状态;
2. 记录状态时,敌人和墙也可以炸

序列型20%

问题特点

  1. 条件 : 一般给一维数组

  2. 状态定义 : 状态dp[i]的含义是前i个元素的序列的性质

  3. 转移方程 : 这种状态定义下对应的转移方程,❗for循环是i <= n( 经常写成i < n,导致输出0)

  4. 返回 : 最后返回dp[n]

刷题记录

Leet Lint 简介 TO SO 收获
Lv256 Li515 刷房子
Lv265 Li556 刷房子,k种颜色 O(n*k)
L198 Li392 打家劫舍
L213 Li534 打家劫舍II 环形街区
L121 Li149 买卖股票的最佳时机(一次交易)
L122 Li150 买卖股票的最佳时机II(多次交易)
L123 Li151 买卖股票的最佳时机III(2次交易)
L188_L面63 Li393 买卖股票的最佳时机IIII(k次交易)
L338 Li664 一个范围内所有的数,各自的数位中1的个数

划分型20%

问题特点

  1. 条件 : 一般字符串或数组
  2. 状态定义 : 状态dp[i]用坐标型的含义
  3. 转移方程 : dp[i]时枚举最后一段的可能的起点
  4. 返回:dp[n - 1]

刷题记录

Leet Lint 简介 TO SO 收获
L91 Li512 编码解析方法
L279 Li513 最少平方数 O(n^3/2) 最优解 🔳四平方数和定理
L132 Li108 分割回文串 O(n^2) 中轴方法判断回文串
/ Li437🐱‍💻 抄书 最优解 🔳贪心二分
求和Trick
L55 Li116 跳跃石头 O(n^2) 最优解 🔳贪心

子序列型5%

LIS:Longest Increasing Subsequence

问题特点

  1. 条件 : 字符串或数组
  2. 状态定义 : 状态dp[i]用坐标型的含义
  3. 转移方程 : /
  4. 返回 : ❗dp[0] ~ dp[n - 1]中的最大值

刷题记录

Leet Lint 简介 时间复杂度 空间复杂度 收获
L300 Li076 最长上升子序列 O(N^2) 🔳patience game解法O(N*logN)
L53 Li41 最大连续子序列和
L354 Li602 信封套娃(和最长上升子序列解法一样) 🔳O(N*logN)
/ Li397 最长单向(上升或下降)连续子序列(最长单向子串) 上升下降分别求

区间型15%

子问题需要去头去尾

问题特点

  1. 条件 : 字符串或数组
  2. 状态定义dp[i][j], 字符i到j的区间的性质
  3. 转移方程 : 循环变量是区间的长度
  4. 返回 : dp[0][n - 1]

刷题记录

Leet Lint 简介 时间复杂度 空间复杂度 收获
L516 Li667 最长回文子序列 O(N^2)
L877 LiV396 只能从两端取数,谁的和最大谁赢
L87 Li430 扰乱字符串🐱‍💻
L312 Li168 戳气球(消去型->区间型)🐱‍💻

背包型10%

载重W的背包,N件待选物品,物品属性:重量w,价值v

问题特点

  1. 条件 : 数组
  2. 状态定义 : 状态dp[i]用序列型的含义,重量一定要记录在状态中
  3. 转移方程:最后一步是最后一个物品 是否进入背包(0-1) / 是哪一个(完全)
  4. 返回 :/

分类

问法分类

  • 可行型
  • 最值型
    • 要求正好装满
    • 不要求正好装满
  • 计数型

要求分类

  • 0-1背包,列表中的物品只有一个

  • 完全背包,列表中的物品有任意个

刷题记录

Leet Lint 简介 时间复杂度 空间复杂度 收获
/ Li92 最值型0-1背包,最大重量
Li125 最值型0-1背包,最大价值
/ Li563 计数型0-1背包,装满的方案数
Li562 计数型完全背包,装满的方案数(不同顺序算一种方案)
/ Li564 计数型完全背包,和为指定值的组合数(不同顺序算不同方案) 描述更复杂解决却更简单(股票问题也是)
L332 Li669 最值型完全背包,换硬币的最少个数
LiV440 最值型完全背包,最大价值

博弈型5%

问题特点

从第一步开始考虑而不是最后一步

弄清楚必胜态,必败态

刷题记录

Leet Lint 简介 时间复杂度 空间复杂度 收获
/ Li394 谁最后没东西拿谁输 O(N)
L877 LiV396 只能从两端取数,谁的和最大谁赢

双序列型

问题特点

  1. 条件 : 字符串或数组
  2. 状态定义dp[i][j], 第一个序列的前i个字符和第二个序列的前j个字符的性质
  3. 转移方程 :最后一步,考虑怎么砍尾巴
  4. 返回 : dp[m][n]

刷题记录

Leet Lint 简介 时间复杂度 空间复杂度 收获
L1143 Li77 最长公共子序列LCS
L97 Li29 交错字符串Iterleaving String
L72 Li119 最小编辑距离Edit Distance

综合型5%

posted @ 2020-05-29 11:22  Leonuoa7  阅读(289)  评论(0编辑  收藏  举报