这里只写个摘要,具体的可以看 神仙Itst的博客
大概是每相邻两个位置之间的线段要么被覆盖一次,要么被覆盖三次,然后DP,如下图:
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 70007 4 #define M 13 5 const int lim=10; 6 const int inf=0x3f3f3f3f; 7 int f[N][M],g[N][M][M]; 8 bool imp[N]; 9 char s[N]; 10 int a[N]; 11 int read() 12 { 13 char c; 14 int x; 15 while((c=getchar())<48||c>57); 16 x=c-48; 17 while((c=getchar())>=48&&c<=57) 18 x=x*10+c-48; 19 return x; 20 } 21 int main() 22 { 23 int n,i,j,k; 24 //freopen("vim.in","r",stdin); 25 n=read(); 26 scanf("%s",s+1); 27 int tot=0,cnt=0; 28 bool flag=false; 29 for(i=1;i<=n;i++) 30 { 31 if(s[i]=='e')cnt++,flag=true; 32 else 33 { 34 a[++tot]=s[i]-'a'; 35 imp[tot]=flag; 36 flag=false; 37 } 38 } 39 memset(f,0x3f,sizeof(f)); 40 memset(g,0x3f,sizeof(g)); 41 f[0][a[1]]=0; 42 for(i=1;i<=tot;i++) 43 { 44 for(j=0;j<=lim;j++) 45 { 46 int t=inf; 47 if(!imp[i]) 48 { 49 if(a[i]!=j)t=min(t,f[i-1][j]); 50 } 51 t=min(t,f[i-1][a[i]]+2); 52 if(a[i]!=j)t=min(t,g[i-1][a[i]][j]); 53 t=min(t,g[i-1][a[i]][a[i]]+2); 54 f[i][j]=t; 55 for(k=0;k<=lim;k++) 56 { 57 int t=inf; 58 //if(!imp[i]) 59 { 60 if(a[i]!=j)t=min(t,f[i-1][j]+3); 61 t=min(t,f[i-1][a[i]]+5); 62 } 63 if(j!=a[i]&&k!=a[i])t=min(t,g[i-1][j][k]+1); 64 if(j!=a[i])t=min(t,g[i-1][j][a[i]]+3); 65 if(k!=a[i])t=min(t,g[i-1][a[i]][k]+3); 66 t=min(t,g[i-1][a[i]][a[i]]+5); 67 g[i][j][k]=t; 68 } 69 } 70 } 71 printf("%d\n",f[tot][lim]-2+2*cnt); 72 return 0; 73 }