区间DP

枚举区间

在线性DP的基础上,区间DP能找到区间的最值。简单的区间DP复杂度为O(n²),如果把f(i,j)f(i, j)定义为[i, j]区间的答案,那么它取决于与它临近解的值:

f[i,j]=g(f[i+1,j],f[i,j1],f[i+1,j1])f[i, j] = g (f[i+1, j], f[i, j-1], f[i+1, j-1])

比如最长回文子串的核心代码:

for l in range(1, N+1):
    for i in range(N-l+1):
        j = i+l-1
        if l<=2: f[i][j] = (s[i]==s[j])
        else: f[i][j] = (f[i+1][j-1] and s[i] == s[j])
        if f[i][j] and l>len(res): res = s[i:j+1]
return res

枚举区间和中点

更复杂的情况,如果问题的大小随着不同阶段变化而变化,那很可能用区间DP来枚举这个动态过程。这个时候时间复杂度为O(n³),那么状态转移方程一般可以写成:

f(i,j)=maxk[f(j,k)+f(k+1,j)+cost]f(i, j) = \max_k [f(j, k) + f(k+1, j) + \text{cost}]

注意上述两种情况中,都是只有区间的长度在不断变大。所以我们一开始都先枚举区间长度 ll 来符合DP的自下而上的要求。

参考模版

用记忆化搜索会更好写些:

例题

枚举区间:

枚举中点:

Last updated

Was this helpful?