LOJ2687 BOI2013Vim 题解

题目链接

这里只写个摘要,具体的可以看 神仙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 }

 

转载于:https://www.cnblogs.com/lishuyu2003/p/11151502.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值