一、简介
区间动态规划简介
区间 DP 是状态的定义和转移都与区间有关,其中区间用两个端点表示。
状态定义 dp[i][j] = [i…j] 上原问题的解。i 变大,j 变小都可以得到更小规模的子问题。
对于单串上的问题,我们可以对比一下线性动态规划和区间动态规划。线性动态规划, 一般是定义 dp[i], 表示考虑到前 i 个元素,原问题的解,i 变小即得到更小规模的子问题,推导状态时候是从前往后,即 i 从小到大推的。区间动态规划,一般是定义 dp[i][j],表示考虑 [i…j] 范围内的元素,原问题的解增加 i,减小 j 都可以得到更小规模的子问题。推导状态一般是按照区间长度从短到长推的。
区间动态规划的状态设计,状态转移都与线性动态规划有明显区别,但是由于这两种方法都经常用在单串问题上,拿到一个单串的问题时,往往不能快速地判断到底是用线性动态规划还是区间动态规划,这也是区间动态规划的难点之一。
状态转移,推导状态 dp[i][j] 时,有两种常见情况
1. dp[i][j] 仅与常数个更小规模子问题有关
一般是与 dp[i + 1][j], dp[i][j - 1], dp[i + 1][j - 1] 有关。
dp[i][j] = f(dp[i + 1][j], dp[i][j - 1], dp[i + 1][j - 1])
代码常见写法
for len = 1..n
for i = i..len
j = i + len - 1
dp[i][j] = max(dp[i][j], f(dp[i+1][j], dp[i][j-1], dp[i+1][j-1]))
时间复杂度和空间复杂度均为 O ( n 2 ) O(n^{2}) O(n2)
2. dp[i][j] 与 O(n) 个更小规模子问题有关
一般是枚举 [i,j] 的分割点,将区间分为 [i,k] 和 [k+1,j],对每个 k 分别求解(下面公式的 f),再汇总(下面公式的 g)。
dp[i][j] = g(f(dp[i][k], dp[k + 1][j])) 其中 k = i … j-1。
代码常见写法, 以下代码以 f 为 max 为例
for len = 1..n
for i = i..len
j = i + len - 1
for k = i..j
dp[i][j] = max(dp[i][j], f(dp[i][k], dp[k][j]))
时间复杂度可以达到 O ( n 3 ) O(n^3) O(n3) 空间复杂度还是 O ( n 2 ) O(n^2) O(n2)
区间动态规划是一种解决单串问题的有效方法,其状态定义与转移涉及区间两端点。与线性动态规划不同,区间DP的状态可以沿着区间长度从短到长推导。本文介绍了两种常见状态转移方式,包括与常数个子问题相关和与O(n)个子问题相关的状态转移,并以最长回文子串问题作为实例进行说明。

1455

被折叠的 条评论
为什么被折叠?



