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 }
View Code

 

posted @ 2017-10-10 20:24  jack_yyc  阅读(189)  评论(0编辑  收藏  举报