【BZOJ 1090】[SCOI2003]字符串折叠

Description

折 叠的定义如下: 1. 一个字符串可以看成它自身的折叠。记作S  S 2. X(S)是X(X>1)个S连接在一起的串的折叠。记作X(S)  SSSS…S(X个S)。 3. 如果A  A’, BB’,则AB  A’B’ 例如,因为3(A) = AAA, 2(B) = BB,所以3(A)C2(B)  AAACBB,而2(3(A)C)2(B)AAACAAACBB 给一个字符串,求它的最短折叠。例如AAAAAAAAAABABABCCD的最短折叠为:9(A)3(AB)CCD。

Input

仅一行,即字符串S,长度保证不超过100。

Output

仅一行,即最短的折叠长度。

Sample Input

NEERCYESYESYESNEERCYESYESYES

Sample Output

14

HINT

一个最短的折叠为:2(NEERC3(YES))

 

又是区间型DP,然后又没推出方程,果真我的DP不是一般的弱啊,hhh

f[i][j]表示最短长度

f[i][j]=min(f[i][k]+f[k+1][j])//不解释

f[i][j]=min(f[i][k]+cal((j-k)/(k-i+1)+1)) //若j-k是k-i+1的n倍。。。

 

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 using namespace std;
 5 int f[110][110];
 6 char s[110];
 7 bool judge(int l,int r,int ll,int rr){
 8     if((r-l+1)%(rr-ll+1)) return 0;
 9     for(int i=l;i<=r;i++) if(s[i]!=s[(i-l)%(rr-ll+1)+ll]) return 0;
10     return 1;
11 }
12  
13 int calc(int x){
14     int t=0;
15     while(x){
16         t++; x/=10;
17     }
18     return t;
19 }
20  
21 int dp(int l,int r){
22     if(l==r) return 1;
23     if(f[l][r]!=-1) return f[l][r];
24     int tmp=(r-l+1);
25     for(int i=l;i<r;i++) tmp=min(tmp,dp(l,i)+dp(i+1,r));
26     for(int i=l;i<r;i++)
27     if(judge(i+1,r,l,i))
28     tmp=min(tmp,dp(l,i)+2+calc((r-i)/(i-l+1)+1));
29     f[l][r]=tmp;
30     return tmp;
31 }
32  
33 int main(){
34     scanf("%s",s+1);
35     int len=strlen(s+1);
36     memset(f,-1,sizeof(f));
37     printf("%d",dp(1,len));
38 }

 

posted @ 2016-02-25 08:26  Alisahhh  阅读(230)  评论(0编辑  收藏  举报