uva 11552(dp)

来源:互联网 发布:mac word转pdf 白边 编辑:程序博客网 时间:2024/06/04 18:19

题意:有一个整数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[N];int num[N], f[N][30], n, mp[N][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]);elsef[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);elsef[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;}


0 0