BZOJ 1090[SCOI2003]字符串折叠
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 }
以上是关于BZOJ 1090[SCOI2003]字符串折叠的主要内容,如果未能解决你的问题,请参考以下文章