uva11552

题意: 给一个长度为n的串n<1000然后将这个串平均分成k分,分别为 s1 s2 s3...sk,这k份中可以任意的交换字母位置 比如uuvuwwuv 切成两份 这样 uuvu 和wwuv 这样然后 重新整理一下就得到了 uuuv 和vuww 这样合并uv和vuw 在将两个合并 得到 uvuw 为4 个能在消的字符,问最后最小的结果是多少。刚开始考虑 交换他们的不同匹配,因为只要考虑两端就行了,贪心的进行交换结果wa了, 考虑dp[i][c]表示在第i部分的末尾放c的最小值,特判只有1种的情况 然后其他的 不能自己当头又当尾就行了 从前一个状态转移而来 如果有相同的就 +len[i]-1 否则就 +len[i]

dp[i][c]=min(dp[i-1][j]+v)j!=c 特判 1  ,v= i中有没有j ?len[i]-1:len[i];

#include <iostream>
#include <cstdio>
#include <string.h>
#include <vector>
using namespace std;
const int maxn = 1005;
int dp[maxn][30];
int ch[maxn][30];
int len[maxn];
vector<int> common[maxn];
char str[maxn];
int k,num;
void inti(int n ){
     for(int i=0; i<=n; ++i)
         for(int j=0; j<26; ++j)
           dp[i][j]=maxn;
}
int main()
{
     int cas;
     scanf("%d",&cas);
     for(int cc=1; cc<=cas; ++cc){
         scanf("%d%s",&k,str);
         int L = strlen(str);
         num=1;
         for(int i=0; i<L; i+=k){
            len[num]=0;
            memset(ch[num],0,sizeof(ch[num]));
            for(int j=i; j<i+k; ++j) ch[num][str[j]-'a']=1;
            common[num].clear();
            for(int j=0; j<26; ++j)
                if(ch[num][j]==1){
                     common[num].push_back(j);
                     len[num]++;
                }
            num++;
        }
        inti(num);
        for(int i=0; i<common[1].size(); ++i)
            dp[1][common[1][i]]=len[1];
        for(int i=2; i<num; ++i){
            int sz=len[i];
            if(sz==1){
                int t=common[i][0];
                for(int j=0; j<26; ++j)
                    if(t==j) dp[i][t]=min(dp[i][t],dp[i-1][j]+sz-1);
                    else dp[i][t]=min(dp[i][t],dp[i-1][j]+sz);
            }else {
                for(int j=0; j<26; ++j)
                   for(int d=0; d<sz; ++d){
                       int t=common[i][d];
                       if(ch[i][j]==1&&t!=j)
                            dp[i][t]=min(dp[i][t],dp[i-1][j]+sz-1);
                       if(ch[i][j]==0) dp[i][t]=min(dp[i][t],dp[i-1][j]+sz);
                   }
            }
        }
        int ans=maxn;
        for(int i=0; i<26; ++i)
            ans=min(ans,dp[num-1][i]);
        printf("%d
",ans);
     }

    return 0;
}
View Code
原文地址:https://www.cnblogs.com/Opaser/p/4041829.html