• 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
  • 相关阅读:
    ACM/ICPC ZOJ1006-Do the Untwist 解题代码
    ACM/ICPC ZOJ1003-Crashing Balloon 解题代码
    数据结构(二)二叉搜索树-非递归实现遍历
    数据结构(一)二叉搜索树-递归实现
    Spark系列(三)SparkContext分析
    Docker系列(九)Kubernetes安装
    Docker系列(八)Kubernetes介绍
    Docker系列(七)Shipyard安装及介绍
    Docker系列(六)路由打通网络示例
    Esper系列(十四)Contained-Event Selection
  • 原文地址:https://www.cnblogs.com/Opaser/p/4041829.html
Copyright © 2020-2023  润新知