给你一个字符串,让你把它压缩,比如gogogo可以压缩成3(go),letsgogogoletsgogogo可以压缩成2(lets3(go)),然后问你压缩后的最短长度。
典型的区间dp
递推方程:dp[j][i]=min(dp[j][i],dp[j][k]+dp[k+1][i]);
dp[j][i]=min(dp[j][i],dp[j][j+k-1]+2+get(tmp));
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <string.h>
#include <iostream>
#include <sstream>
using namespace std;
const int Nmax=1505;
int dp[Nmax][Nmax];
char s[10005];
int check(int be,int en,int k) //判断i到j这一段区间能否分为长度为k的若干个区间
{
if((en-be+1)%k) return 0;
for(int i=be+k;i<=en;i+=k)
{
for(int j=0;j<k;j++)
{
if(s[i+j]!=s[be+j])return 0;
}
}
return (en-be+1)/k;
}
int get(int x) //返回一个数的位数
{
if (x >= 0 && x <= 9) return 1;
else if (x >= 10 && x <= 99) return 2;
else return 3;
}
int main()
{
int t;cin>>t;
while(t--)
{
scanf("%s",s);
int temp,n=strlen(s);
memset(dp,0x3f3f3f3f,sizeof dp);
for(int i=0;i<n;i++)
dp[i][i]=1;
for(int i=0;i<n;i++)
{
for(int j=i-1;j>=0;j--)
{
for(int k=j;k<i;k++) //可以分成两个子区间的和
dp[j][i]=min(dp[j][i],dp[j][k]+dp[k+1][i]);
for(int k=1;k<=(i-j+1)/2;k++) //把区间分为长度为k的tmp块
{
int tmp=check(j,i,k); //如果所求区间可以分为tmp块
if(tmp) dp[j][i]=min(dp[j][i],dp[j][j+k-1]+2+get(tmp));
}
}
}printf("%d\n",dp[0][n-1]);
}
return 0;
}