链接
https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2547
题解
记录每一块的颜色数
cnt[i]
c
n
t
[
i
]
,用
bool
b
o
o
l
数组
color[i][j]
c
o
l
o
r
[
i
]
[
j
]
表示第
i
i
个块中有没有出现这种颜色
f[i][j]
f
[
i
]
[
j
]
表示第
i
i
块的末尾是颜色,前
i
i
块的最小色块数,枚举第块的颜色
k
k
当时,若
j=k
j
=
k
,
f[i][j]←f[i−1][k]
f
[
i
]
[
j
]
←
f
[
i
−
1
]
[
k
]
,若
j≠k
j
≠
k
,
f[i][j]←f[i−1][k]+1
f
[
i
]
[
j
]
←
f
[
i
−
1
]
[
k
]
+
1
当
cnt[i]>1
c
n
t
[
i
]
>
1
时,若
j=k
j
=
k
,则
f[i][j]←f[i−1][k]+cnt[i]
f
[
i
]
[
j
]
←
f
[
i
−
1
]
[
k
]
+
c
n
t
[
i
]
,若
j≠k
j
≠
k
,
f[i][j]←f[i−1][k]+cnt[i]−color[i][k]
f
[
i
]
[
j
]
←
f
[
i
−
1
]
[
k
]
+
c
n
t
[
i
]
−
c
o
l
o
r
[
i
]
[
k
]
注意边界
代码
//DP
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cctype>
#define maxn 1010
#define inf 0x3f3f3f3f
#define cl(x,y) memset(x,y,sizeof(x))
using namespace std;
int f[maxn][30], cnt[maxn], color[maxn][30], K, N;
char s[maxn];
void init()
{
int i, j;
cl(f,inf);
cl(cnt,0);
cl(color,0);
scanf("%d%s",&K,s);
N=strlen(s);
for(i=0;i<N;i++)s[i]=s[i]-'a'+1;
for(i=0;i<N;i++)color[i/K][s[i]]=1;
for(i=0;i<N/K;i++)for(j=1;j<=26;j++)cnt[i]+=color[i][j];
}
void dp()
{
int i, j, k, ans=inf;
for(i=1;i<=26;i++)if(color[0][i])f[0][i]=cnt[0];
for(i=1;i<N/K;i++)for(j=1;j<=26;j++)for(k=1;k<=26;k++)
if(color[i-1][k] and color[i][j])
if(cnt[i]==1)
{
if(j==k)f[i][j]=min(f[i][j],f[i-1][k]);
else f[i][j]=min(f[i][j],f[i-1][k]+1);
}
else
{
if(j==k)f[i][j]=min(f[i][j],f[i-1][k]+cnt[i]);
else f[i][j]=min(f[i][j],f[i-1][k]+cnt[i]-color[i][k]);
}
for(i=1;i<=26;i++)ans=min(ans,f[N/K-1][i]);
printf("%d\n",ans);
}
int main()
{
int T;
for(scanf("%d",&T);T--;)init(), dp();
return 0;
}