zoukankan      html  css  js  c++  java
  • UVA

    A common way to uniquely encode a string is by replacing its consecutive repeating characters (or “chunks”) by the number of times the character occurs followed by the character itself. For example, the string “aabbbaabaaaa” may be encoded as “2a3b2a1b4a”. (Note for this problem even a single character “b” is replaced by “1b”.) Suppose we have a string S and a number k such that k divides the length of S. Let S1 be the substring of S from 1 to k, S2 be the substring of S from k + 1 to 2k, and so on. We wish to rearrange the characters of each block Si independently so that the concatenation of those permutations S ′ has as few chunks of the same character as possible. Output the fewest number of chunks. For example, let S be “uuvuwwuv” and k be 4. Then S1 is “uuvu” and has three chunks, but may be rearranged to “uuuv” which has two chunks. Similarly, S2 may be rearranged to “vuww”. Then S ′ , or S1S2, is “uuuvvuww” which is 4 chunks, indeed the minimum number of chunks.

    Input

    The input begins with a line containing t (1 ≤ t ≤ 100), the number of test cases. The following t lines contain an integer k and a string S made of no more than 1000 lowercase English alphabet letters. It is guaranteed that k will divide the length of S.

    Output

    For each test case, output a single line containing the minimum number of chunks after we rearrange S as described above.

    题解:

      这个题目还算好写。

      首先我们考虑一种简化的情况假设全部只有一组会怎么样?贪心的思考一下只要将所有的字母相同的放在一起,然后统计块数就可以了。那么如果用多个组结果是哪里不同呢?

      如果我们把前一个组的最后一个块和当前组的最开始一个组放在一起(前提:颜色相同),那么数量就可以少一,思考到这状态就是显然的了!设dp[i][j]为dp到第i组并且当前这个组的最后一个块的颜色是i的最小花费。转移有两个一个不管怎样就是强行把所有的块塞到前一组的末尾——dp[i][j]=min(dp[i][j],dp[i-1][k]+num[i]),第二个转移,当前一组最后一个块的颜色和当前这组一种颜色相同时就可以把他们拼在一起,所以就只要加num[i]-1,即:dp[i][j]=min(dp[i][j],dp[i-1][k]+num[i]-1);有小细节,写的时候注意一下就可以了。

    代码:

    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<stdio.h>
    #include<stdlib.h>
    #define MAXN 1010
    using namespace std;
    int num[MAXN],have[MAXN][27];
    int dp[MAXN][27];
    char a[MAXN];
    int n,k,tot;
    int main(){
        int t;scanf("%d",&t);
        while(t--){
            scanf("%d",&k),scanf("%s",a+1);
            n=strlen(a+1);
            memset(num,0,sizeof(num));
            memset(have,0,sizeof(have));
            memset(dp,127/3,sizeof(dp));
            for(int i=1,hao=1;i<=n;i+=k,hao++)
            for(int j=i;j<i+k;j++){
                if(!have[hao][a[j]-'a']) num[hao]++;
                have[hao][a[j]-'a']=1;
            }
            tot=n/k;
            for(int i=0;i<=25;i++) dp[0][i]=0;
            for(int i=1;i<=tot;i++)
            for(int j=0;j<=25;j++){
                if(!have[i][j]) continue;
                for(int k=0;k<=25;k++) dp[i][j]=min(dp[i][j],dp[i-1][k]+num[i]);
                if(i!=1)
                for(int k=0;k<=25;k++){
                    if(have[i][k]==0) continue;
                    if(k==j&&num[i]!=1) continue;
                    dp[i][j]=min(dp[i][j],dp[i-1][k]+num[i]-1);
                }
            }
            int ans=1<<30;
            for(int i=0;i<=25;i++) ans=min(ans,dp[tot][i]);
            printf("%d
    ",ans);
        }
    }
  • 相关阅读:
    协议详解1——概要
    协议学习之 vamei博客系列 总结
    DDOS介绍
    python基础教程总结15——7 自定义电子公告板
    python基础教程总结15——6 CGI远程编辑
    python基础教程总结15——5 虚拟茶话会
    python基础教程总结15——4 新闻聚合
    python基础教程总结15——3 XML构建网址
    如何在远程桌面的服务器上访问本地磁盘
    C# 如何把dataTable以参数的形式传入 sql 存储过程
  • 原文地址:https://www.cnblogs.com/renjianshige/p/7458318.html
Copyright © 2011-2022 走看看