[线头dp] Jzoj P3320 文本编辑器

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

 

题解

  • 新玩意
  • 推荐大家去看这篇博客(点我
  • 详细明了

代码

 1 #include <cstdio>
 2 #include <iostream>
 3 #include <cstring>
 4 using namespace std;
 5 const int N=70010,M=11;
 6 int n,cnt,f[N][M],g[N][M][M];
 7 char s[N];
 8 bool col[N];
 9 int main()
10 {
11     scanf("%d",&n),scanf("%s",s+1);
12     col[1]=1,s[1]-='a';
13     for (int i=2;i<=n;i++)
14     {
15         if (s[i]=='e') cnt++; else if (s[i-1]==4) col[i]=1;
16         s[i]-='a';    
17     }
18     memset(f,63,sizeof(f)),memset(g,63,sizeof(g)),f[0][s[1]]=0;
19     for (int i=1;i<=n;i++)
20     {
21         if (s[i]==4) 
22         {
23             memcpy(f[i],f[i-1],sizeof(f[i])),memcpy(g[i],g[i-1],sizeof(g[i]));
24             continue;
25         }
26         for (int j=0;j<M;j++)
27         {
28             if (j!=s[i]&&!col[i]) f[i][j]=min(f[i-1][j],f[i][j]);
29             f[i][j]=min(f[i][j],f[i-1][s[i]]+2);
30             if (s[i]!=j) f[i][j]=min(f[i][j],g[i-1][s[i]][j]);
31             f[i][j]=min(f[i][j],g[i-1][s[i]][s[i]]+2);
32             for (int k=0;k<M;k++)
33             {
34                 if (j!=s[i]) g[i][j][k]=min(g[i][j][k],f[i-1][j]+3);
35                 g[i][j][k]=min(g[i][j][k],f[i-1][s[i]]+5);
36                 if (j!=s[i]&&k!=s[i]) g[i][j][k]=min(g[i][j][k],g[i-1][j][k]+1);
37                 if (k!=s[i]) g[i][j][k]=min(g[i][j][k],g[i-1][s[i]][k]+3);
38                 if (j!=s[i]) g[i][j][k]=min(g[i][j][k],g[i-1][j][s[i]]+3);
39                 g[i][j][k]=min(g[i][j][k],g[i-1][s[i]][s[i]]+5);    
40             } 
41         }
42     }
43     printf("%d",f[n][M-1]+cnt*2-2);
44 } 

 

posted @ 2019-07-08 15:59 BEYang_Z 阅读(...) 评论(...) 编辑 收藏