这个问题比上一个简单一点,应该对比一下两题的相似与不同点,来找到解题的技巧
这题是用递推实现的,不用记忆化。
f【l】【r】表示,把l~r这个区间折叠的最短长度,
然后我们想,对于一个区间来说,我们有两种选择,一种是把这个区间它自己来折叠,另一种是两块已经折叠的区间接起来。
对于第二中情况,直接枚举断点(两道题中都用到的思路),再和答案取min,第一种则是,找出它所有的折叠方案,在折叠方案中取一个最优的
此题与上一题,思路的整理类比和分析:
首先这都是两道有关字符串压缩的题目,整体的思路都是对于一段区间,两类决策
1:由子问题更新的最优决策2:该区间本身进行压缩(进行处理)的最优决策
但是bzoj1068,M与R构成类似大括号进行压缩,但是一个M对应了不止一个R,这就是麻烦所在(不好转移),bzoj1090,就是括号对应括号,相对形象
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
using namespace std;
const int inf=0x3f3f3f3f;
int f[105][105],g[105][105],n;
char s[105];
inline int tt(int x)
{
if (x<10) return 1;
if (x<100) return 2;
return 3;
}
bool pan(int l,int r,int len)
{
for (int i=1;i<=len;i++)
{
bool o=true;
for (int j=l+i-1;j+len<=r;j+=len)
if (s[j]!=s[j+len]) return false;
}
return true;
}
int main()
{
scanf("%s",s+1);
n=strlen(s+1);
for (int l=n;l>=1;l--)
{
f[l][l]=1;
for (int r=l+1;r<=n;r++)
{
f[l][r]=r-l+1;
for (int i=l;i<r;i++)
f[l][r]=min(f[l][r],f[l][i]+f[i+1][r]);
int len=r-l+1;
for (int i=1;i<=len;i++)
if (len%i==0&&pan(l,r,i))
f[l][r]=min(f[l][r],f[l][l+i-1]+2+tt(len/i));
}
}
printf("%d",f[1][n]);
return 0;
}