jzoj3320. 文本编辑器&LOJ2687. 「BalticOI 2013」Vim

Description

在这里插入图片描述

Input

第一行包含了整数N,表示该文档的长度。下一行包含N个字符,每一个都是十个小写字母“a”到“j”之一。输入的第一个和最后一个字母都不是“e”。

Output

输出一个整数,表示Victor需要删除所有的“e”最少的按键次数。

Sample Input

35
chefeddiefedjeffeachbigagedegghehad

Sample Output

36

解释:其中一个最优方案是:fdhxhhxffhxfahxhhhxhhhxfdhxfghxfahhx

Data Constraint

50%数据:N ≤ 500
另外10%的数据:N ≤ 5000
100%的数据:N ≤ 70 000

题解

50%
考虑DP。
我们设状态(f_{[i,j]})表示当前第i个位置,把前j个e都给删去的最小步数。
怎么转移?
由于每个f操作都是往右跳,h是往左跳。
那么我们发现,每次从i往右跳到j后,一定是把i到j里面的所有e都删去后才继续往右跳,否则不优。
那么每次都是把某一段的e都给删掉。
于是就很好转移的,每次考虑枚举下一个e是什么,利用预处理求出代价后转移。
注意各种小细节。
时间复杂度:(O(n^3))
60%
我不费。(其实是我没打过)
似乎转移状态和上面的很相似,设(f_{[i,j]})表示当前第i个位置,1~j位置的所有e都去掉的最小步数。
我们发现,每次j是只可能往右走,而i往左跳或往右跳都是可以的。
那么我们固定一个k,分两种情况:
1、f操作。枚举一个新的字符,然后i往右跳。
2、h操作。我们如果k右边i左边有e没删,那么就把i往左边跳即可。
实际上转移好像比较猎奇。
但是时间是(O(n^2*10))的。
100%
这据说是一个叫线头DP的玩意儿,我从来没有听说过。
似乎DP比较神奇,理解起来也很容易。
(主要是题解很棒)
https://www.cnblogs.com/Itst/p/10339605.html、
https://www.cnblogs.com/cjyyb/p/11146822.html
看完你就懂了。比我写得详细多了。
其中有一个东东没有讲得特别清楚:
就是DP方程其实记录的是当前第i个位置以前的h操作和f操作。
所以说在看到q的转移的时候我们可以看到它没有求i+1到j这部分的答案。
这个地方注意,其他都很容易。

标程

uses math;
var
        i,j,k,l,n,m,len,maxx,si:longint;
        mip:array[1..70000] of boolean;
        p:array[0..70000,1..11] of longint;
        q:array[0..70000,1..11,1..11] of longint;
        s,t:ansistring;
begin
        //assign(input,'2data.in');reset(input);
        readln(n);
        readln(s);
        for i:=1 to n do
        begin
                if s[i]='e' then
                begin
                        inc(m);
                end
                else
                begin
                        inc(len);
                        t:=t+s[i];
                        if (i>1) and (s[i-1]='e') then
                        begin
                                mip[len]:=true;
                        end;
                end;
        end;
        inc(len);
        t:=t+'k';
        fillchar(p,sizeof(p),127 div 3);
        fillchar(q,sizeof(q),127 div 3);
        maxx:=p[0,1];
        p[0,ord(t[1])-96]:=0;
        q[0,ord(t[1])-96,ord(t[1])-96]:=0;
        for i:=1 to len do
        begin
                si:=ord(t[i])-96;
                for j:=1 to 11 do
                begin
                        p[i,j]:=min(p[i-1,si]+2,q[i-1,si,si]+2);
                        if (j<>si) and (not mip[i]) then p[i,j]:=min(p[i,j],p[i-1,j]);
                        if (j<>si) then p[i,j]:=min(p[i,j],q[i-1,si,j]);
                        for k:=1 to 11 do
                        begin
                                q[i,j,k]:=min(p[i-1,si]+5,q[i-1,si,si]+5);
                                if (j<>si) then q[i,j,k]:=min(q[i,j,k],min(p[i-1,j]+3,q[i-1,j,si]+3));
                                if (k<>si) then q[i,j,k]:=min(q[i,j,k],q[i-1,si,k]+3);
                                if (j<>si) and (k<>si) then q[i,j,k]:=min(q[i,j,k],q[i-1,j,k]+1);
                        end;
                end;
        end;
        writeln(m*2-2+p[len-1,11]);
end.
原文地址:https://www.cnblogs.com/RainbowCrown/p/11153777.html