zoukankan      html  css  js  c++  java
  • 动态规划习题分类题解 (202103)

    动态规划习题分类题解 (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) 的本质不同子串的数量,则

    [f[i][j]=f[i-1][j]+f[i-1][j-1]-f[pre[i]-1][j-1] ]

    [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) 行的前缀和,则

    [egin{aligned} f[i][j] & =s[i+1][j+k-1]-s[i+1][j-1]+ \ max_l & egin{cases} f[i-1][l]+s[i][j+k-1]-s[i][j-1] & (1 leq l leq j-k) \ f[i-1][l]+s[i][j+k-1]-s[i][l+k-1] & (j-k+1 leq l leq j) \ f[i-1][l]+s[i][l-1]-s[i][j-1] & (j+1 leq l leq j+k-1) \ f[i-1][l]+s[i][j+k-1]-s[i][j-1] & (j+k leq l leq m-k+1) end{cases} end{aligned} ]

    如果暴力转移,则复杂度 (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) 次,则转移方程

    [f[i][j]=max_k (f[k][j-frac{i-k}{2}]+m[k+1][i]cdot (i-k)) ]

    其中 (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]) 的最短前缀的长度

  • 相关阅读:
    边框的各种样式
    内容溢出显示省略号
    UNIAPP开发注意事项
    css文本的三条线 删除线 下划线 上划线
    防抖截流
    浏览器窗口改变触发的函数
    ES5数组方法
    弹性布局
    ubuntu16.04 安装adb
    git clone
  • 原文地址:https://www.cnblogs.com/mollnn/p/14553559.html
Copyright © 2011-2022 走看看