bzoj 1068 [SCOI2007]压缩 区间dp

[SCOI2007]压缩

Time Limit: 1 Sec  Memory Limit: 128 MB
Submit: 1644  Solved: 1042
[Submit][Status][Discuss]

Description

  给一个由小写字母组成的字符串,我们可以用一种简单的方法来压缩其中的重复信息。压缩后的字符串除了小
写字母外还可以(但不必)包含大写字母R与M,其中M标记重复串的开始,R重复从上一个M(如果当前位置左边没
有M,则从串的开始算起)开始的解压结果(称为缓冲串)。 bcdcdcdcd可以压缩为bMcdRR,下面是解压缩的过程

 

  另一个例子是abcabcdabcabcdxyxyz可以被压缩为abcRdRMxyRz。

Input

  输入仅一行,包含待压缩字符串,仅包含小写字母,长度为n。

Output

  输出仅一行,即压缩后字符串的最短长度。

Sample Input

bcdcdcdcdxcdcdcdcd

Sample Output

12

HINT

在第一个例子中,解为aaaRa,在第二个例子中,解为bMcdRRxMcdRR。 

【限制】 

100%的数据满足:1<=n<=50 100%的数据满足:1<=n<=50

题解:

    这题就是一个普通的区间dp

 1 #include<cstring>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<iostream>
 5 #include<cmath>
 6 #include<queue>
 7 
 8 #define N 1007
 9 using namespace std;
10 inline int read()
11 {
12     int x=0,f=1;char ch=getchar();
13     while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
14     while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
15     return x*f;
16 }
17 
18 char s[100];
19 int f[60][60][2];
20 bool mark[60][60][2];
21 
22 bool same(int a,int b)
23 {
24      int l=b-a+1;
25      if(l&1)return 0;
26      for(int i=a;i<=(a+b)/2;i++)
27         if(s[i]!=s[i+l/2])return 0;
28      return 1;
29  }
30 int dp(int a,int b,bool t)
31 {
32     int tmp=b-a+1;
33     if(tmp==1)return 1;
34     if(mark[a][b][t])return f[a][b][t];
35     mark[a][b][t]=1;
36     if(t)for(int i=a;i<b;i++)tmp=min(tmp,dp(a,i,1)+dp(i+1,b,1)+1);
37     for(int i=a;i<b;i++)tmp=min(tmp,dp(a,i,t)+b-i);
38     if(same(a,b))tmp=min(tmp,dp(a,(a+b)/2,0)+1);
39     return f[a][b][t]=tmp;
40 }
41 int main()
42 {
43     scanf("%s",s+1);
44     int l=strlen(s+1);
45     printf("%d",dp(1,l,1));
46     return 0;
47 }
原文地址:https://www.cnblogs.com/fengzhiyuan/p/8834246.html