uva11552

来源:互联网 发布:mac不能保存书签 编辑:程序博客网 时间:2024/05/17 06:51

做过难的dp再做这种,就能很清晰的发现状态转移过程中关键的状态量

就是第i组结束后末尾的字母

dp[i][j]表示前i组,以j结尾的最少块数

dp[i][j] 转移时要转移到全部的dp[i-1][k] 分成k等于j和k不等于j分别考虑

难得1A,水题。。

#include<stdio.h>#include<string.h>#include<algorithm>#include<iostream>const int INF = 111111111;using namespace std; int main() { int t; scanf("%d",&t); while(t--){ char s[1005]; int have[1005][27]; int num[1005];int dp[1005][27];int k,l,part; memset(have,0,sizeof(have)); memset(num,0,sizeof(num)); memset(dp,0,sizeof(dp));scanf("%d",&k);scanf("%s",s); l = strlen(s); part = l / k; for(int i = 1; i <= part; i++){ int start = (i - 1)*k;for(int j = 0; j < k; j++){    if (have[i][s[start + j] - 'a'] != 1)        num[i]++;have[i][s[start + j] - 'a'] = 1;        }        //printf("%d\n",num[i]);    }    for(int j = 0; j <= 25; j++)       dp[1][j] = have[1][j]?num[1] : INF;    for(int i = 2; i <= part; i++)for(int j = 0; j <= 25; j++){if (!have[i][j]){dp[i][j] = INF;continue;}dp[i][j] = INF;for(int q = 0; q <= 25; q++){if (q == j){if (num[i] == 1) dp[i][j] = min(dp[i][j],dp[i - 1][q]);else dp[i][j] = min(dp[i][j],dp[i - 1][q] + num[i]);}else{if (have[i][q]) dp[i][j] = min(dp[i][j],dp[i - 1][q] + num[i] - 1);else dp[i][j] = min(dp[i][j],dp[i - 1][q] + num[i]);}}}int ans = INF;for(int j = 0; j <= 25; j++)   ans = min(ans,dp[part][j]);printf("%d\n",ans); } return 0; }

0 0