您的位置:首页 > 其它

uva11552

2016-04-02 17:24 267 查看
做过难的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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  acm dp