您的位置:首页 > 其它

uva 11552(dp)

2015-04-17 23:30 393 查看
题意:有一个整数k和一个字符串,字符串的长度一定是k的倍数,那么可以把字符串分成k组,可以把每组的字符串重组但组的先后顺序不变,连续字母的称为一块,问整个字符串可以形成的最少块是多少。

题解:可以先把字符串出现的字母个数和种类数都统计出来,f[i][j]表示第i组前以j字母为结尾的最少块数量,枚举字母找到f[i][j]与f[i - 1][k]的关系更新出f[i][j]。最后过一遍f[len/k - 1][j]得到最小值。

#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <map>
using namespace std;
const int N = 1005;
const int INF = 0x3f3f3f3f;
char str
;
int num
, f
[30], n, mp
[30];

int main() {
int t;
scanf("%d", &t);
while (t--) {
scanf("%d%s", &n, str);
int len = strlen(str);
int m = len / n;
for (int i = 0; i < m; i++) {
memset(mp[i], 0, sizeof(mp[i]));
for (int j = n * i; j < n * i + n; j++)
mp[i][str[j] - 'a']++;
num[i] = 0;
for (int j = 0; j < 26; j++)
if (mp[i][j])
num[i]++;
}
memset(f, INF, sizeof(f));
for (int i = 0; i < 26; i++)
if (mp[0][i])
f[0][i] = num[0];
for (int i = 1; i < m; i++)
for (int j = 0; j < 26; j++) {
if (!mp[i][j])
continue;
for (int k = 0; k < 26; k++) {
if (!mp[i - 1][k])
continue;
if (j == k) {
if (num[i] == 1)
f[i][j] = min(f[i][j], f[i - 1][k]);
else
f[i][j] = min(f[i][j], f[i - 1][k] + num[i]);
}
else {
if (num[i] == 1)
f[i][j] = min(f[i][j], f[i - 1][k] + 1);
else
f[i][j] = min(f[i][j], f[i - 1][k] + num[i] - (mp[i][k] > 0));
}
}
}
int res = INF;
for (int i = 0; i < 26; i++)
res = min(res, f[m - 1][i]);
printf("%d\n", res);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  dp uva