UVA_11552_FewestFlops

来源:互联网 发布:广告单页设计软件 编辑:程序博客网 时间:2024/06/08 05:04

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".)

 Fewest Flops


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.
Sample Input
2
5 helloworld
7 thefewestflops
Sample Output
8
10


动态规划题目,只是dp数组中存储的是最后一位是26个字母中的某个的最小段数

因此每刷过一段从新统计下dp

注意到后一个dp可以用到所有之前的dp因此又开了一个ddp数组来记录当前的状态,随后用它更新dp

并不是区间dp,或者说不用

#include <iostream>#include <stdio.h>#include <string.h>using namespace std;const int M=1005;int cha[26];int dp[26];int ddp[26];char s[M];int main(){    int t;    int n;    int f;    int co;    scanf("%d",&t);    while(t--)    {        f=co=0;        memset(cha,0,sizeof(cha));        scanf("%d%s",&n,s);        int l=strlen(s);        for(int i=0;i<n;i++)            cha[s[i]-'a']++;        int num=0;        for(int i=0;i<26;i++)            if(cha[i])                num++;        for(int i=0;i<26;i++)        {            if(cha[i])                dp[i]=num;            else                dp[i]=M;        }        int numn=0;        for(int ii=n;ii<l;ii+=n)        {            numn=0;            memset(cha,0,sizeof(cha));            for(int i=ii;i<ii+n&&i<l;i++)                cha[s[i]-'a']++;            for(int i=0;i<26;i++)                if(cha[i])                    numn++;            for(int j=0;j<26;j++)                    ddp[j]=M;            for(int i=0;i<26;i++)             //枚举结束            {                if(!cha[i])               //没有当前字母i                {                    continue;                }                if(numn==1)               //当前串中只有一种字母                {                    if(dp[i]<M)               //前结尾有i                        ddp[i]=min(ddp[i],dp[i]);                    for(int j=0;j<26;j++)           //前结尾不是i                        ddp[i]=min(ddp[i],dp[j]+1);                    break;                }                for(int j=0;j<26;j++)         //枚举开始                {                    if(dp[j]<M&&cha[j])              //之前的结尾有j&&现在的字母有j                    {                        if(j!=i)                    //串首和串尾不相同                            ddp[i]=min(ddp[i],dp[j]+numn-1);                    }                    ddp[i]=min(ddp[i],dp[j]+numn);                }            }            for(int j=0;j<26;j++)                    dp[j]=ddp[j];        }        int ans=M;        for(int i=0;i<26;i++)            ans=min(ans,dp[i]);        printf("%d\n",ans);    }    return 0;}


0 0
原创粉丝点击