您的位置:首页 > 其它

BZOJ 1090 字符串折叠(区间DP)

2016-06-02 17:43 357 查看
题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1090

题意:字符串AAAAAAAAAABABABCCD的最短折叠为9(A)3(AB)CCD,注意数字的长度和圆括号都算最后长度。求一种折叠方式使得总长度最小。

思路:记忆化搜索。

#include<algorithm>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
char s[500005],a[500005];
int f[5005][5005];
bool ok(int l,int r,int len){
int L=0;
for (int i=l;i<=l+len-1;i++)
a[++L]=s[i];
int num=(r-l+1)/len;
for (int i=1;i<=num;i++)
for (int j=1;j<=len;j++)
if (a[j]!=s[l+(i-1)*len+j-1]) return 0;
return 1;
}
int cal(int x){
if (x<10) return 1;
if (x<=99) return 2;
return 3;
}
int dp(int l,int r){
if (f[l][r]!=-1) return f[l][r];
if (l==r) return 1;
int len=r-l+1;
f[l][r]=len;
for (int i=l;i<r;i++)
f[l][r]=std::min(f[l][r],dp(l,i)+dp(i+1,r));
for (int i=1;i<len;i++)
if (len%i==0&&ok(l,r,i)) f[l][r]=std::min(f[l][r],dp(l,l+i-1)+cal(len/i)+2);
return f[l][r];
}
int main(){
scanf("%s",s+1);
int n=strlen(s+1);
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
f[i][j]=-1;
printf("%d\n",dp(1,n));
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: