#19488. 二维DP题单简介

二维DP题单简介

你好!看到你的成绩单,作为教练,我首先要肯定你的状态定义能力——你在 1D DP 和基础背包问题上的逻辑非常清晰。

你目前遇到的瓶颈是 “多序列/字符串匹配类 DP”。这类问题的核心在于决策的同步性:是两个序列各推进一步(斜对角线),还是其中一个序列先停下而另一个推进一步(水平或垂直)。

为了帮你突破这个瓶颈,我为你制定了以下针对性方案。


第一部分:洛谷针对性补课题单

建议按照以下顺序练习,重点体会“状态从哪里来”:

  1. P2758 编辑距离(核心加练):直接针对你错的第 7 题,强制练习三种操作的逻辑转换。
  2. P1439 【模板】最长公共子序列:针对第 9 题。注意这题有 O(n2)O(n^2)O(nlogn)O(n \log n) 两种写法,先吃透 O(n2)O(n^2) 的二维转移。
  3. P1140 相似基因序列:这是编辑距离的变种,你会发现它本质上是在填一张得分表,通过这题区分“匹配成功”和“与空字符匹配”。
  4. P1216 [USACO1.5] 数字三角形:虽然简单,但它是所有 2D 路径 DP 的鼻祖,用来巩固“上方/左上方”的来源判断。
  5. P1006 传纸条:进阶练习。这题涉及两条路径同时走,是对“多维度状态转移”的终极考验。

第二部分:预备知识点总结

在做这些题之前,请确保你理解以下概念:

  1. 笛卡尔坐标系下的状态依赖:理解 dp[i][j] 在二维表中的几何位置(左、上、左上)。
  2. 边界初始化:字符串 DP 中,当一个字符串长度为 0 时,另一个字符串需要全部删除/添加的操作数(即 dp[i][0]dp[0][j] 的含义)。
  3. 滚动数组优化:二维 DP 如何压缩成一维,从而优化空间复杂度(从 O(N2)O(N^2)O(N)O(N))。

第三部分:启发式思维引导(草稿纸上的推理)

现在,拿出一张草稿纸。我们以 “最长公共子序列 (LCS)” 为例,模拟你的思考过程。

1. 绘制状态表

假设字符串 A = ABC, B = AC。我们在纸上画一个 4x3 的方格(包含第 0 行/列)。

"" A B C
"" 0 0
A ?
C

2. 启发式提问与图形思考

情景 A:当 A[i] == B[j] 时(例如 A[1]='A', B[1]='A')

  • 思考:这两个字母匹配成功了,它们是不是共同占用了 LCS 的一个长度?
  • 动作:在格子里画一个斜向右下的箭头 ↘️。
  • 推导:既然这两个字母都用了,那长度就是“去掉这两个字母后的结果” + 1。
  • 结论dp[i][j] = dp[i-1][j-1] + 1 (来自左上角)。

情景 B:当 A[i] != B[j] 时(例如 A[2]='B', B[2]='C')

  • 思考:这两个字母不相等,没法配对。那我可以尝试把 A 的 'B' 扔掉,或者把 B 的 'C' 扔掉。
  • 动作:画一个向右 ➡️ 和向下 ⬇️ 的箭头。
  • 推导
    • 扔掉 A 的 'B':看 dp[i-1][j] (上方)
    • 扔掉 B 的 'C':看 dp[i][j-1] (左方)
  • 结论:取两者最大值 max(dp[i-1][j], dp[i][j-1])

3. 复杂度分析思考

  • 时间复杂度:我们在填一个 N×MN \times M 的表格,每个格子只算一次。复杂度 O(N×M)O(N \times M)
    • 优化建议:如果 N,MN, M 达到 10510^5,必须考虑 O(NlogN)O(N \log N) 算法(利用 LIS 转化,见模板题 P1439)。
  • 空间复杂度:默认 O(N×M)O(N \times M)
    • 优化建议:观察发现计算 dp[i] 只需要 dp[i-1] 的数据。可以用 “滚动数组” 将空间压至 O(M)O(M)

第四部分:读题关键词总结

在 DP 题目中,一旦看到以下关键词,就要警惕是否需要 二维状态转移

  1. “两个序列/两个字符串”
    • 含义:大概率需要 dp[i][j],其中 ii 表示第一个序列的进度,jj 表示第二个。
  2. “子序列 (Subsequence)” vs “子串 (Substring)”
    • 子序列:不要求连续(转移往往涉及 max(dp[i-1][j], dp[i][j-1]))。
    • 子串:必须连续(如果不匹配,状态可能直接重置为 0)。
  3. “最小操作次数” / “编辑”
    • 含义:通常涉及 3 种来源(增、删、改),对应左、上、左上。
  4. “刚好匹配” 或 “配对”
    • 含义:这是对角线转移(左上角)的强烈信号。

教练寄语: 你在做题时,可以在草稿纸上画一个小方块,标出 (i, j)。每次转移前问自己:“如果我想求这个格子的最优解,我的最后一步动作是只消耗 A只消耗 B、还是同时消耗 A 和 B?” 只要分清这三点,二维 DP 就不再是难点。加油!