动态规划习题分类题解 (202103) - 3. 进阶高维DP
[CF10D]LCIS
DESCRIPTION
求两个串的最长公共上升子序列 (n,m < 500)
SOLUTION
关键是在设置状态的时候,强制以某一维参量为结尾
设 (f[i][j]) 表示选取分别选取前 i,j 个元素,并且以 (b[j]) 结尾,组成的 LCIS 最长是多少
转移的时候,只需要考虑 ai,bj 的情况
如果 ai=bj,那么一方面可以放弃 i,从 (i-1,j) 转移,另一方面也可以找一个更小更前面的 t,从 (i-1,t) 转移,答案获得 1 的增量
否则,只能从 (i-1,j) 转移
记录一下转移来源,然后递归输出答案即可
[CF917B]MADMAX
DESCRIPTION
有一个 DAG,每条边上有一个小写英文字母表示权值,Alice 和 Bob 每人有一个棋子,各放在一个节点上(可以放在同一个节点上)。第一轮 Alice 可以沿一条边把棋子移到一个相邻的节点上,之后 Bob 沿一条边移动棋子,以此类推。规则规定每一次移动经过的边的 ASCII 码单调不降。不能走的人输。对于所有的初始位置,两人都按最优策略,问谁会赢。(nleq 100)
Solution
设 (f[i][j][k]) 表示先手位于 (i),后手位于 (j),边权为 (k) 对应的胜负情况
对于 (i) 所有出点 (q),状态转移为 (f[j][q][w])
如果至少存在一个 (q) 使得 (f[j][q][w]) 为 (0),那么 (f[i][j][k]) 为 (1),否则为 (0)
[CF1149B]ThreeReligions
Description
给定长度为 (n) 的母串和三个子串 (s_1,s_2,s_3)。初始时子串均为空。
有 (q) 次询问。你需要支持两种操作:向某个子串末尾添加一个字母,或者删去某个子串末尾的字母。
在每次操作后,你需要回答,是否能从母串中分离出三个不相交的子序列,满足这三个子序列恰好是 (s_1,s_2,s_3)。
在任意时刻,(s_1,s_2,s_3) 的长度均不会超过 (250)。
(1 le n le 10^5) , (1le q le 10^3)
Solution
设 (f[i][j][k]) 表示三个子串分别匹配到了第 (i,j,k) 个字符,在母串中推进的最短距离
设 (g[i][c]) 表示 (S[i..n]) 内字符 (c) 第一次出现的位置
[CF1181C]Flag
Description
一面国旗可以抽象为一个 $ n imes m (n,m le 1000)$ 的矩形,每一个位置有一个颜色。这个矩形由自上而下三条横向的颜色带组成,每一条颜色带宽度相等,而且相邻两个颜色带颜色不能相同。现在你有一个 $ n imes m $ 的矩形,你需要计算其中能够称为国旗的子矩形数量。
Solution
预处理 (f[i][j]) 表示以元素 ((i,j)) 为顶端,在满足颜色相同的条件下,能向下延伸的最长距离
然后计算以每个点为右上角的 Flag 数量
对于单列的判断,只需要使用几个条件即可,判定位置 (i+3d-1) 合法,并且 (i+d,i+2d) 的 (f) 值满足条件
考虑复列,如果第 (j) 列与第 (j-1) 列的颜色对应相同,并且延伸数符合条件,则将计数器 (+1),否则将计数器置 (1)
(用好题目条件来构造算法,简直太妙了)
[CF1183H]Subsequences(hardversion)
Description
你有一个长度为 $ n le 100 $ 的字符串。对于一个长度为 $ m $ 的子序列,选出它的花费是 $ n-m $,也就是你需要删掉的字符数量。你的任务是选出 $ k $ 个本质不同的子序列,使得总花费最小。输出这个最小花费。如果选不出 $ k $ 个,输出 $ -1 $。
Solution
设 (pre[i]) 表示 (i) 的前驱位置,设 (f[i][j]) 表示前 (i) 个字符,长度为 (j) 的本质不同子串的数量,则
[CF1303E]EraseSubsequences
Description
- 给定两个字符串 (s) 和 (t)。
- 询问能否找到 (s) 的两个不相交的子序列(可以为空) (s_1,s_2) 使 (t=s_1s_2)。
- 多组数据,(Tle100),(1le|t|le|s|le400),其中 (|s|) 表示 (s) 的长度。
Solution
不由分说地枚举分割点
令 (f[i][j]) 表示原串处理到 (i) ,(s_1) 处理到 (j),(s_2) 最多能处理到哪里
采用主动转移
任意情况, (f[i][j] o f[i+1][j])
如果 (s[i+1]=s_1[j+1]) ,那么 (f[i][j] o f[i+1][j+1])
如果 (s[i+1]=s_2[f[i][j]+1]) ,那么 (f[i][j]+1 o f[i+1][j])
时间复杂度 (O(n^3))
[CF1304F2]AnimalObservation
Description
计划拍摄森林中的野生动物们。森林被划分为 (m) 个地区,依次编号为 (1) 到 (m),他的拍摄计划持续 (n) 天。
每一天,他会选择森林中连续的 (k) 个地区,并且录一段长为 (2) 天的录像。(如果是最后一天,那就录一段长度为 (1) 天的录像)这样所有在这两天之内在这 (k) 个地区中出现过的动物都会被拍摄到。
他知道未来 (n) 天内每一天每一个地区会出现多少野生动物。他想拍摄下尽可能多的野生动物。注意如果一个动物被拍摄了两次,那么只会被计算一次。
你的任务是求出拍摄到的动物数量的最大值。
(nle 50,mle 20000,kle m)
Solution
设 (f[i][j]) 为第 (i) 天在第 (j) 个位置放置的最大值,设 (s[i][j]) 是第 (i) 行的前缀和,则
如果暴力转移,则复杂度 (O(nm^2 ))
如果 (k) 很小,那么对中间两种情况暴力转移,旁边两种由于只有 (f[i-1][l]) 与 (l) 有关,可以预处理前后缀 (max) 来解决,复杂度 (O(nmk))
当 (k) 变大时,两侧的情况仍然暴力转移,中间的情况可以暴力用以 (l) 为下标的单调队列维护 (f[i-1][l]-s[i][l+k-1]) 和 (f[i-1][l]+s[i][l-1])
[CF1336C]KaaviandMagicSpell
Description
给定一个字符串 (S) 和一个字符串 (T),每次操作可以从 (S) 的开头删去一个字符,把它加到一个初始为空的串的开头或结尾,不必删完,求有多少种不同的方法使得 (T) 是 (A) 的前缀。
Solution
所谓要求 (T) 是 (A) 的前缀,即要求 (A) 的前 (T) 个字符是 (A)。
考虑 dp,设 (f[i][j]) 表示用 (S) 的前 (j-i+1) 个字符构造出 (T[i..j]) 的方案数。
考虑转移,每次若 (T[i]=S[j-i+1]),那么 (f[i][j] leftarrow f[i+1][j]),反过来也同理。
初态条件可以直接令所有 (f[i][i-1]=1)。
最终的答案即为 (sum_{i=|T|}^{|S|} f[1][i])。
WannaflyWinterCamp2020Day6I变大!
Description
给定一个序列,可以执行 (k) 次操作,每次选择连续的三个位置,将他们都变成他们的最大值,最大化 (sum a_i)
需要对每一个 (k=i) 输出答案
(n leq 50, a_i leq 20),数据组数 (leq 100)
Solution
我们考虑将这些数分段,每段刷成区间内的最大值,那么很显然就可以 DP 了
(f[i][j]) 表示搞定了前 (i) 个数,操作了 (j) 次,则转移方程
其中 (m[l][r]) 表示 ([l,r]) 这段区间的最大值,可以暴力预处理得到
总体时间复杂度 (O(Tn^3))
2020杭电多校第二场L-StringDistance
Description
给定两个字符串 (S,T),每个询问会指定 (S) 的一个子串和 (T) 作为两个操作串 (A,B),每次可以选择任意一个字符串插入/删除一个字母,回答使得两个操作串相同的最小代价。(|S| le 10^5, |T| le 20)
Solution
插入操作是没用的,于是两个串的距离为 (|A|+|B|-2LCS(A,B))
预处理 (g[i][j]) 表示 (A[i..n]) 中字符 (j) 最早出现的下标
对于每个询问,暴力 DP
设 (f[i][j]) 表示与 (B[1..i]) 的公共序列长度达到 (j) 的 (A[l..r]) 的最短前缀的长度