bzoj 1090 字符串折叠
题目大意:
折叠的定义如下: 1. 一个字符串可以看成它自身的折叠。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
思路:
区间dp
对于每一段可以枚举切割点
同时有特殊情况,即有一段可以表示为它的子段的循环,这时候需要加上循环次数的数字位数以及括号
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<algorithm> 5 #include<cstring> 6 #include<cstdlib> 7 #include<queue> 8 #include<vector> 9 #include<set> 10 #include<stack> 11 #define inf 2147483611 12 //define ll long long 13 #define MAXN 110 14 using namespace std; 15 char ch[MAXN]; 16 int len,dp[MAXN][MAXN]; 17 bool ok(int ll,int lr,int rl,int rr) 18 { 19 if((rr-rl+1)%(lr-ll+1)!=0) return 0; 20 for(int i=rl;i<=rr;i+=lr-ll+1) 21 { 22 for(int j=0;j<=lr-ll;j++) 23 { 24 if(ch[ll+j]!=ch[i+j]) return 0; 25 } 26 } 27 return 1; 28 } 29 int cnt(int x) {int res=0;while(x) {x/=10;res++;}return res;} 30 int main() 31 { 32 scanf("%s",ch+1); 33 int len=strlen(ch+1); 34 for(int i=1;i<=len;i++) dp[i][i]=1; 35 for(int l=1;l<=len;l++) 36 for(int i=1;i+l<=len;i++) 37 { 38 dp[i][i+l]=inf; 39 for(int j=i;j<i+l;j++) 40 { 41 dp[i][i+l]=min(dp[i][i+l],dp[i][j]+dp[j+1][i+l]); 42 if(ok(i,j,j+1,i+l)) dp[i][i+l]=min(dp[i][i+l],dp[i][j]+cnt((i+l-j)/(j-i+1)+1)+2); 43 } 44 45 } 46 printf("%d",dp[1][len]); 47 }