题意:就是说一开始一个序列是空的,然后每次可以将连续的一段染成同一颜色,问多少次才能到目标状态。
一开始想的是二分,然后题解DP。。。
f[i][j]表示区间[i,j]需要染色多少次
首先初始状态是f[i][i]=1和f[i][i+1]=str[i]==str[i+1]
然后从短区间地推到长区间
对于f[i][j],若str[i]==str[j],则有f[i][j]=min{f[i+1][j],f[i][j-1],f[i+1][j-1]+1},否则f[i][j]=min{f[i][k]+f[k+1][j]∣i≤k<j}
复杂度:O(n^3)
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
#define N 60
int len;
int f[N][N];
char str[N];
int main()
{
scanf("%s",str+1);
len=strlen(str+1);
memset(f,127/3,sizeof(f));
for (int i=1;i<=len;i++)
f[i][i]=1;
for (int l=1;l<=len;l++)
for (int i=1;i<=len-l;i++)
{
int j=i+l;
if (str[i]==str[j])
if (l==1)
f[i][j]=1;
else
{
f[i][j]=min(f[i+1][j],f[i][j-1]);
//f[i][j]=min(f[i][j],f[i+1][j-1]+1);删了这句更快,0ms。。
}
else
for (int k=i;k<j;k++)
f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]);
}
printf("%d
",f[1][len]);
return 0;
}