NOIP2024集训Day23 DP常见模型3 - 区间
NOIP2024集训Day23 DP常见模型3 - 区间
A. [CSP-S 2021] 括号序列
区间 dp,令 \(f_{l, r}\) 表示从位置 \(l\) 到位置 \(r\) 一共的合法序列总情况数量。
一共有六种不同的转移情况,所以将 \(f_{l, r}\) 扩充到三维。
- 全是
* (...)(...)**(...)***,左边以括号序列开头,右边以*结尾(...)**(...)**(...),均以括号序列开头和结尾(包含形态二)***(...)***(...),左边以*开头,右边以括号序列结尾***(...)**(...)***,左右均以*结尾(包含形态一)
转移(序号对应上边的形态):
-
直接特判(暴力判断两端的距离是否 \(\le k\),是的再转移)
-
\(f_{l, r, 1} = (f_{l +1, r - 1, 0} + f_{l + 1, r - 1, 2} + f_{l + 1, r - 1, 3} + f_{l + 1, r - 1, 4}) \times \operatorname{check}(l, r)\),其中 \(\operatorname{check}(l, r)\) 表示判断 \(l\) 和 \(r\) 是否能匹配括号
-
\(f_{l, r, 2} = \sum\limits_{i = l}^{r -1} f_{l, i, 3} \times f_{i + 1, r, 0}\)
均以括号序列开头和结尾是 3,右边接一串
*,是 0。 -
\(f_{l, r, 3} = \sum\limits_{i = l}^{r - 1}(f_{l, i, 2} + f_{l, i, 3}) \times f_{i + 1, r, 1} + f_{l, r, 1}\)
左边以括号序列开头,结尾随便,符合的有 2 和 3,右边接一个括号序列,是 1,还要加上直接一个括号序列的。
-
\(f_{l, r, 4} = \sum\limits_{i = l}^{r - 1}(f_{l, i, 4} + f_{l, i, 5})\times f_{i + 1, r, 1}\)
左边以
*开头,结尾随便,符合的有 4 和 5,右边接一个括号序列,是 1。 -
\(f_{l, r, 5} = \sum\limits_{i = l}^{r - 1} f_{l, i, 4} \times f_{i + 1, r, 0} + f_{l, r, 0}\)
左边以
*开头,以括号序列结尾,符合的是 4,右边接一串*,是 0,还要加上全是*的。
答案必须是以括号序列开头,括号序列结尾,于是为 \(f_{1, n, 3}\)。
初始化:对于所有的 \(1\le i\le n\),有 \(f_{i, i - 1, 0} = 1\)。
时间复杂度 \(\Theta(6\times n^3)\) 不到。
B. [BalticOI 2009 Day1] 甲虫
区间 dp。
在枚举一个 \(c\),表示要喝 \(c\) 滴水的前提下,记 \(f_{l, r, 0}\) 表示喝完区间 \([l, r]\) 的水且在 \(l\) 的浪费的水的最小体积,\(f_{l, r, 1}\) 表示在 \(r\)。所谓浪费的水体积也就是蒸发掉的水体积数,其中包括已经和掉的 \(r - l + 1\) 滴和没有喝的 \(c - (r - l + 1)\) 滴。所浪费的水体积就是 \((c - (r - l + 1))\times \Delta x\)。
方程:定义 \(len = r - l + 1\)。
\(f_{i, j, 0} = \min(f_{l + 1, r, 0} + (c - len + 1) \times (x_{l + 1} - x_l), f_{l + 1, r, 1} + (c - len + 1) \times (x_r - x_l))\)
\(f_{i, j, 1} = \min(f_{l, r - 1, 1} + (c - len + 1) \times (x_r - x_{r - 1}),f_{l, r - 1, 0} + (c - len + 1) \times (x_r - x_l))\)
C. 方块消除
区间 dp。难点在于消除一块后,可能会有后面的继续并上。
定义状态 \(f_{i, j, p}\) 表示,仍然只考虑区间 \([i, j]\),但此时我知道 \(j\) 后面有 \(p\) 个和 \(j\) 颜色相同的块,在该种情况下能得到的最大收益。
对于 \(f_{i, j, p}\) 有如下几种决策:
-
直接消除 \(j + p\) 这一段,收益为 \(f_{i, j - 1, 0} + (x_j + p)^2\)。
-
分段处理,将区间分成两部分,每部分单独考虑贡献,然后再相加。
在 \([i, j - 1]\) 中找一个与 \(j\) 颜色相同的坐标 \(k\),将区间分为 \([i, k]\) 和 \([k + 1, j - 1]\),此时的两个子状态分别为 \(f_{i, k, x_j + p}\) 和 \(f_{k + 1, j - 1, 0}\)。意义就是先消除 \([k + 1, j - 1]\) 这一段,然后把后面那一坨并过来。
当 \(i=j\) 时,直接返回 \((x_j + p)^2\)。
F. [AGC020E] Encoding Subsets
区间 dp。加入考虑标准的区间,子集等定义不好处理。
考虑对字符串做 dp。设 \(f(S)\) 表示一个串 \(S\) 及其所有子集的压缩方案数。
转移方式:
- \(S_0\) 不压缩,直接从 \(f(S_{1\sim |S| - 1})\) 转移过来。
- \(S_0\) 与后面的压缩。
枚举循环节长度以及循环次数,找到所有循环串的交集,然后转移。
用 map 维护 dp。

浙公网安备 33010602011771号