zoukankan      html  css  js  c++  java
  • 从 vim 一题看线头 DP 的扩展应用

    线头 DP

    我们知道,线头 DP 是我们搞定一类只和两侧元素有关的排列问题的利器。

    我们在数轴上,将排列中相邻的两个数连线,这样得到一条折线。以边为单位,考察穿过这条边的折线段的影响,进行动态规划。

    线头 DP 在更广泛的折线路径类问题上的应用

    我们以「BalticOI 2013」Vim 为例分析线头 DP 的扩展应用。

    既然我们知道,线头 DP 先将排列转为了折线,我们就可以拿它来解决更广泛的折线路径类问题。

    在本题中,我们可以将光标的移动视为折线。注意到我们删除一个 $e$,一定是在该 $e$ 之后的那个位置进行操作 hx。因此所有的 $e$ 都需要两步,这样我们删去那些 $e$,问题转化为经过一些关键点(原左边为 $e$ 的位置)的最小步数了。

    我们将 f 操作引发的折线叫作飞线,h 操作引发的折线叫作跳线。我们知道,折线路径一定是这样的:每次先通过若干次飞线连成的飞链降落在某点,然后往回跳到出发点右侧第一个关键点。

    为了计算答案的清晰性,我们认为每次操作的步数都在起点计算。

    从两个点之间的间隙将折线剪开,至多会剪断两条飞线和一条跳线。如果没有剪到飞线,那么说明整个折线已经结束了。我们知道飞线的降落地点只和其字符有关。

    于是我们设 $f(i, j, k)$ 表示在第 $i$ 个字符右侧剪开折线,剪到的两条飞线中所属飞链起点较左的那条的字符为 $j$,所属飞链起点较右的那条的字符为 $k$ 时,在前 $i$ 个字符内计算的步数最小值。特别地,$k=mbox{nil}$ 表示它只穿过了一条飞线。

    根据这个我们进行分类讨论,设计动态规划。

    由于最后一段飞链回跳后可以不必再引出飞线,所以要特殊考虑。我们在倒数第二段飞链结束的时候来计算答案。

    我们利用序列自动机,求出第 $i$ 个点右边第一个字符 $j$ 的位置 $mbox{next}_{ij}$ 和第 $i$ 个点右边第一个关键点 $mbox{nextkey}_i$。那么,如果最后一条飞链在第 $i$ 个点降落,且最后一条飞链跳到了 $j$,设最后一个关键点位置为 $mbox{lastkey}$,那么就要满足 $jge mbox{lastkey}$,回跳的步数为 $j-mbox{nextkey}_i$。

    因此我们令 $d(i)$ 表示从第 $i$ 个点经过 $s$ 条飞线降落在 $t$,使 $t ge mbox{lastkey}$ 时最小的 $2s+t$,进行动态规划。

    于是答案就是 $minig{f(i, j, mbox{nil})+d(mbox{next}_{ij})-mbox{nextkey}_i ig| 1 le i lt mbox{lastkey}, j in {a, b, c, d, f, g, h, i, j}ig}$。

  • 相关阅读:
    你了解JWT吗?
    链接
    C#读取EXCEL发生错误
    TM1637驱动数码管
    Keil中的Code,RO,RW,ZI分别表示什么
    IE 不支持 promise 解决方法
    JS 时间戳转日期格式
    JS input 输入框只能输入 字母和汉字
    小程序 保存图片失败
    小程序充值,方法步骤
  • 原文地址:https://www.cnblogs.com/nealchen/p/10162980.html
Copyright © 2011-2022 走看看