zoukankan      html  css  js  c++  java
  • 解题营_动规

    动态规划

    前言

    8.20

    写过去的时间比较久了 也懒得补代码了 思路问题不是很大 扔下了...

    大多数的题已经做完了 代码其实是有的 但是隔得时间比较久了 再回来写就感觉写不下去了.

    再找机会吧

    当然做过的题目在洛谷上都是可以找到提交记录的..

    题目

    P2704 炮兵阵地

    经典的状压 (dp)

    P5933 串珠子

    状压

    联通难以处理 正难则反 考虑算出不联通的方案数 再用总方案数减去

    (f_S) 表示选点状态为 (S) 时 有多少联通子图

    联通子图的数量不容易计算 考虑计算不联通的子图数量

    随便钦定 (S) 内的一个点 (p) 枚举 (p) 所在的联通块 (T in S) 预处理 (g_S) 表示 (S) 内的子图数量(所有边的乘积)

    P1777 帮助

    将移动 (k) 分为两步 先删 再插入被删的数

    如果已知删去的是那些数 插入的时候可以贪

    一个数在插入过程中产生代价当且仅当该数在删除过程中删干净了

    数的种类可以压

    仅考虑删除 设 (f_{i, j, x}) 表示仅考虑前 (i) 个数 从中删掉 (j) 个数且最后剩下的数是 (x) 的最小混乱度

    考虑插入步骤产生的影响 直接压没被删掉的数的集合 设 (f_{i, j, x, S}) 表示 考虑前 (i) 个数 删去 (j) 个数 最后剩下的数为 (x) 且未被删除的数的集合为 (S) 时的最小混乱度

    P6622 信号传递

    从第 (i) 个位置传到第 (j) 个位置 如果 (i < j) 则 时间为 (j - i) 否则为 (K imes (i + j))

    信号站的数量少 可以压

    信号传递的顺序无关紧要 只序言知道对于每个 (i, j) 有多少次从 (i) 传到 (j) 和有多少次从 (j) 传到 (i)

    预处理每两个信号站之间的传递次数

    对于位置 (x, y) 的两个信号站 如果有 (A) 次从左到右 和 (B) 次从右到左 那么产生的时间为 (A(y - x) + BK(x + y))

    (f_S) 表示给 (S) 内的信号站排序的最小传递时间 每加入一个点算它作为 (x)(y) 的时间贡献

    P3959 宝藏

    点数少 压点集 枚举子集

    最后打通的为一棵树

    代价和点到根的距离有关 考虑距离

    按照离根的距离一层一层加点

    (f_{i, S}) 表示打通 (S) 这个集合 距离根最远的点为 (i) 的最小代价 转移枚举距离为 (i) 的子集 (T) 然后对于 (T) 中每个点在 (S/T) 里找到代价最小的点

    Pay to Win

    通过以下操作将 (0) 变成 (N)

    • (A) 将数字乘 (2)
    • (B) 将数字乘 (3)
    • (C) 将数字乘 (5)
    • (D) 将数字加一或减一

    (N leq 10^{18})

    (f_x) 表示将 (0) 变为 (x) 的最小代价

    第一个乘法前可能有若干个加一

    将一次乘法和若干次加法绑定成一次操作

    复杂度为 (O(N))

    可以采用记搜 避开转移不到 (N) 的状态 有用的 (x) 只有 (frac N{2^a3^b5^c}) 的上取整或下取整形式

    P3174 毛毛虫

    确定一条链就能确定一个对应的毛毛虫 相当于求链

    一条链可以断成两段 设 (f_u) 表示以 (u) 为根的子树中以 (u) 为端点的链能抽出的毛毛虫的最大值 维护最大和次大儿子

    P1472 奶牛家谱

    恰好为 (K) 比较麻烦 改为 不超过 (K)

    (f_{i, j}) 表示有多少点数为 (i) 最大深度不超过 (j) 的二叉树 转移枚举左儿子的点数

    P1131 时态同步

    对每个节点 其包含的所有叶子到它的距离相同

    (f_u) 表示将 (u) 为根的字数内时态同步的最小代价

    转移找最大的到叶子的距离 其他儿子与该距离做差

    P1623 树的匹配

    (f_{u, 0/1}) 表示 (u) 为根的子树内的 (u) 点是否选的最大匹配数量

    [f_{u, 0} = sum max(f_{v, 0}, f_{v, 1})\ d = f_{v, 0} - max(f_{v, 0}, f_{v, 1})\ d = min(0, f_{v, 0} - f_{v, 1})\ f_{u, 1} = f_{u, 0} + 1 + d ]

    (f_{u, 0/1}) 表示 (u) 为根的子树内 (u) 点是否选的匹配数匹配方案数

    [f_{u, 0} = prod (f_{v, 0} + f_{v, 1})\ f_{u, 1} = f_{u, 0}sum frac{f_{v, 0}}{f_{v, 0} + f_{v, 1}} ]

    (g_{u, 0/1}) 表示 (u) 为根的子树内最大匹配

    (f_{u, 0/1}) 表示 (u) 为根的子树内 (u) 点是否选的最大匹配的方案数

    [f_{u, 0} = prod ([g_{v, 0} geq g_{v, 1}] f_{v, 0} + [g_{v, 0} leq g_{v, 1}]f_{v, 1})\ f_{u, 1} = f_{u, 0} imes sum_{d_v = d} frac {f_{v, 0}}{[g_{v, 0} geq g_{v, 1}] f_{v, 0} + [g_{v, 0} leq g_{v, 1}]f_{v, 1}} ]

    通过 (g) 判断转移是否可行

    P5322 排兵布阵

    要么直接占下来 要么不派

    (f_{i, j}) 表示在前 (i) 个城堡派遣 (j) 个士兵的最大得分 转移枚举第 (i) 个城堡派遣的士兵数量(其他玩家派的兵力乘 (2)(1))

    P4141 消失之物

    容斥或者卷

    P1272 重建道路

    树上背包

    (Y) 的背包计数问题

    (f_{i, j}) 表示使用前 (i) 个物品装满体积和为 (j) 的背包的方案数

    转移枚举第 (i) 个数用了多少个

    [f_{i, j} = sum_{k = 0}^i f_{i - 1, j - i imes k} ]

    复杂度 (O(n^3))

    一般的多重背包

    二进制拆分 (O(n^2log n))

    对于方案数

    单调队列 (O(n^2))

    前缀和优化

    预处理 (g_{i, j})

    [g_{i, j} = sum_{k = 0}^{lfloor frac ji floor} f_{i, j - ki} ]

    转移

    [f_{i, j} = g_{i - 1, j} - g_{i - 1, j - i imes (i - 1)} ]

    P3216 数学作业

    (f_i) 表示将 (1)(i) 拼起来 如果 (i) 的位数为 (k) 则转移为 (f_i = f_{i - 1} imes 10^k + i)

    对于 (k) 相同的一段数 可以用矩阵快速幂优化 ({f_i, f_{i + 1}, i})

    P2579 沼泽鳄鱼

    若没有食人鱼 设 (f_u) 表示走到 (u) 点的方案数 (g_u) 是多走一步到达 (u) 点的方案数 有 (g = f imes A) 其中 (A) 为原图的邻接矩阵 所以走 (K) 步就是求 (A^K)

    考虑食人鱼的话 可以将食人鱼的周期直接看做 (12) 设当前食人鱼在周期中走到 (i)(g = f imes A imes B_i) 其中 (B_i) 只在对角线上没有食人鱼的点上有值

    于是要求的矩阵变为 (AB_1AB_2AB_3dots AB_{K mod 12 + 1}) 将每十二个绑到一起 做矩阵快速幂 剩下的直接乘上去

    P3205 合唱队

    每个人只能插入到最左边或最右边 不能插入到中间

    在插入的过程中队形始终对应最终队形的一个区间

    区间 (dp)

    (f_{l, r, 0/1}) 表示排列成区间 ([l, r]) 的序列 最后一个数插入左边还是右边的方案 转移枚举倒数第二个人插入左边还是右边

    P4302 字符串折叠

    区间 (dp)

    (f_{l, r}) 表示将 ([l, r]) 折叠的最小长度

    转移考虑两种情况

    多个折叠构成 枚举分解点分成两个

    本身就是一个折叠 该串由若干小串重复若干次得到

    枚举小串的长度 小串的长度必须整除原串的长度 确定小串长度后再暴力判断原串是否由小串重复得到

    AT2558 Many Moves

    (f_{i, j}) 表示处理前 (i) 个要求后两个棋子的位置分别在 (x_i)(j)

    [f_{i + 1, j} = f_{i, j} + |x_i - x_{i + 1}|\ f_{i + 1, x_i} = f_{i, j} + |j - x_{i + 1}| ]

    复杂度 (O(qn))

    以线段树分别维护 (f_{i, j}, f_{i, j} + j, f_{i, j} - j) 的第二个维度

    (i) 看做时间轴 以 (j) 为下标 随着 (i) 的改变 维护线段树

    对于上面第一个式子 相当于全局加

    第二个式子 (min (f_{i + 1, x_i}, f_{i, j} + |j - x_{i + 1}|))

    分类讨论拆绝对值

    (j leq x_{i + 1})(min (f_{i, j} + x_{i + 1} - j))

    (j > x_{i + 1})(min (f_{i, j} + j - x_{i + 1}))

    (x_{i + 1}) 是固定的可以拿出来

    线段树中维护 (f_{i, j} + j)(f_{i, j} - j)

    P1850 换教室

    (f_{i, j, 0/1}) 表示前 (i) 个教室 申请其中 (j) 个 最后一个是否申请的最小期望代价

    转移枚举上一个教室是否申请

    CF908D New Year and Arbitrary Arrangement

    无穷等比数列求和 当 (0 < q < 1)

    [sum_{i = 1}^{infty} q^i = frac 1{1 - q} ]

    在最后加一个 (a) 没有影响 在最后加一个 (b) 会增加若干个 (ab) 序列

    (f_{i, j}) 表示当前有 (i)(a)(j)(ab) 子序列的状态加到最后期望 (ab) 子序列的数量是多少

    [f_{i, j} = A imes f_{i + 1, j} + B imes f_{i, j + i} ]

    (j geq k)

    [f_{i, j} = j ]

    第一维没有边界

    (i) 限制在 (k) 以内 考虑如果直接求 (f_{k, j}) 的值

    第二维会超过 (k) 直接带入值

    [f_{k, j} = Af_{k + 1, j} + B(j + k)\ = A^2f_{k + 2, j} + AB(j + k + 1) + B(j + k)\ = dots\ = sum_{i = 0}^{infty}A^iB(j + k + i)\ = sum_{i = 0}^{infty}A^iB(j + k) + sum_{i = 0}^{infty}A^iBi\ = B(j + k)sum_{i = 0}^{infty}A^i + Bsum_{i = 1}^{infty}A^ii ]

    对于前面那一坨东西 有:

    [B(j + k)sum_{i = 0}^{infty}A^i = frac {B(j + k)}{1 - A} = j + k ]

    对于后面那一坨东西

    设:

    [sum_{i = 1}^{infty}A^ii = Q ]

    有:

    [Q - AQ = A + sum_{i = 2}^{infty}A^i = sum_{i = 1}^{infty}A^i = frac A{1 - A} ]

    所以:

    [Q = frac A{(1 - A)^2} = frac A{B^2} ]

    故原式可化为:

    [j + k + frac AB ]

    得到了 (f_{k, j}) 的值

    所以

    (i = k)(f_{i, j} = i + j + frac AB)

    (j geq k)(f_{i, j} = j)

    复杂度 (O(k^2))

    答案为 (f_{0, 0})

    CF713C Sonya and Problem Wihtout a Legend

    (b_i = a_i - i)

    (a_i leq a_{i + 1} - 1) 等价于 (b_i leq b_{i + 1})

    (f_{i, j}) 表示将前 (i) 个数变为单调不减且 (b_i = j) 的操作数

    [f_{i, j} = |b_i - j| + min_{k leq j}(f_{i - 1, k}) ]

    后面那一坨东西是前缀最小值 可以预处理

    [g_{i, j} = min(f_{i, j}, g_{i, j - 1})\ f_{i, j} = |b_i - j| + g_{i - 1, j} ]

    复杂度与值域有关 离散化

    P2511 木棍分割

    第一问显然可以二分 第二问 (dp)

    (f_{i, j}) 表示前 (i) 个数分为 (j) 段 每段不超过 (x) 的方案数

    转移枚举最后一段的长度

    [f_{i, j} = sum_{k = 1}^i f_{i - k, j - 1}[sum_{i - k + 1, i} leq x] ]

    复杂度 (O(mn^2)) 显然可以超时

    (k) 的枚举是有边界的 将 (dp) 数组的第一维可以前缀和优化

    边界 也就是以每一个位置作为右端点的最大区间 是可以二分或者双指针 找到边界后可以把后面那东西去掉

    P5999 kangaroo

    相当于求有多少排列大小交替并且第一个和最后一个分别为 (s)(t)

    对于一个合法的排列 (p) 如果只考虑不超过 (x) 的值 (p) 会被划分为若干连续段

    (f_{i, j}) 表示考虑不超过 (i) 的值 有多少最终排列能被划分为恰好 (j) 段的方案数

    转移考虑加入 (i)(i) 是单独作为一个段或是将两个相邻的段连接成了一个段

    由于 (i) 是当前最大值 所以 (i) 不会作为段的端点

    [f_{i, j} = f_{i - 1, j + 1} imes j + f_{i - 1, j - 1} imes (j - [i > s] - [i > t])\ f_{s, j} = f_{s - 1, j} + f_{s - 1, j - 1}\ f_{t, j} = f_{t - 1, j} + f_{t - 1, j - 1} ]

    答案为 (f_{n, 1})

    P6280 Exercise G

    对于每个位置建图的话会形成若干个环 所以 (K) 就是所有环长的 (lcm)

    (lcm) 只需要考虑每个质数的指数

    相当于 求所有 (K) 的和满足 (K) 质因数分解后所有的 (p^x) 加起来不超过 (n)

    (f_{i, j}) 表示前 (i) 个质数 所有 (p^x) 加起来为 (j)(K) 的和

    [f_{i, j} = f_{i - 1, j} + sum_{x > =}f_{i - 1, j - p^x} imes p^x ]

    CF348D Turtles

    可以看做一只从 ((1, 2))((n - 1, m)) 另一条从 ((2, 1))((n, m - 1)) 不妨设为 (A, B, C, D)

    两只乌龟可以分别 (dp) 再合并 考虑如果剔除相交的方案

    对于 (A o B, C o D) 的任意一条相交路径都可以在第一个交点位置翻折 得到 (A o D, C o B) 的路径 这两者是一一对应的关系 所以方案数相同

    做两次 (dp) 再相乘 即 ((A o B) imes (C o D) - (C o B) imes (A o D))

    P1453 城市环路

    基环树独立集

    (f_{u, 0/1}) 表示 (u) 为根的子树中最大独立集

    找一条边断掉 跑树形 (dp) 即可

  • 相关阅读:
    BZOJ 1040 (ZJOI 2008) 骑士
    BZOJ 1037 (ZJOI 2008) 生日聚会
    ZJOI 2006 物流运输 bzoj1003
    ZJOI 2006 物流运输 bzoj1003
    NOI2001 炮兵阵地 洛谷2704
    NOI2001 炮兵阵地 洛谷2704
    JLOI 2013 卡牌游戏 bzoj3191
    JLOI 2013 卡牌游戏 bzoj3191
    Noip 2012 day2t1 同余方程
    bzoj 1191 [HNOI2006]超级英雄Hero——二分图匹配
  • 原文地址:https://www.cnblogs.com/blank-space-/p/15168259.html
Copyright © 2011-2022 走看看