uva Fewest Flops(dp)@

Fewest Flops

2000ms
131072KB
This problem will be judged on UVA. Original ID:  11552
64-bit integer IO format:  %lld      Java class name:  Main
Font Size:   
Type: 
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •                    
  • [PDF Link]

    Problem F

    FEWEST FLOPS

    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 tokS2 be the substring of S from + 1 to 2k, and so on. We wish to rearrange the characters of each block Siindependently 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 be “uuvuwwuv” and be 4. Then S1 is “uuvu” and has three chunks, but may be rearranged to “uuuv” which has two chunks. Similarly, Smay be rearranged to “vuww”. Then S’, or S1S2, is “uuuvvuww” which is 4 chunks, indeed the minimum number of chunks.

    Program Input

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

    Program Output

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

    INPUT

    2 5 helloworld 7 thefewestflops 
    OUTPUT
    8
    10
    


    给你一个字符串,长度为k的整数倍,要你分成每个长度为k的段 每个段内可以重新编排,连续的几个字母看作一个块问最少有几个块

    解:枚举每一个段中的K个字符谁当末尾,然后贪心选择,dp[i][j]表示,第i段第j个字符做末尾时的最小块


    #include <iostream>
    #include <bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    const int N = 1e6+7;
    const int inf = 0x3f3f3f3f;
    const LL mod  = 10000007;
    char str[1100];
    int vis[1100], dp[1007][1007];
    
    int main()
    {
        int t;
        scanf("%d", &t);
        while(t--)
        {
            int k;
            scanf("%d %s",&k, str);
            int len=strlen(str);
            memset(dp,0x3f3f3f3f,sizeof(dp));
            for(int l=1; l<=(len/k); l++)
            {
                memset(vis,0,sizeof(vis));
                for(int i=1; i<=k; i++)
                {
                    int pre=(l-1)*k+i-1;
                    vis[str[pre]]++;
                }
                int cnt=0;
                for(int i='a'; i<='z'; i++)
                    if(vis[i]) cnt++;
                if(l==1)
                {
                    for(int i=1;i<=k;i++)  dp[1][i]=cnt;
                    continue;
                }
                for(int i=1;i<=k;i++)
                {
                    int rear=(l-1)*k+i-1;
                    for(int j=1;j<=k;j++)
                    {
                        int pre=(l-2)*k+j-1;
                        if(vis[str[pre]]&&(str[pre]!=str[rear]||cnt==1)) dp[l][i]=min(dp[l][i],dp[l-1][j]+cnt-1);
                        else dp[l][i]=min(dp[l][i],dp[l-1][j]+cnt);
                    }
                }
            }
            int ans=0x3f3f3f3f;
            for(int i=1;i<=k;i++) ans=min(ans,dp[len/k][i]);
            cout<<ans<<endl;
        }
        return 0;
    }

    评论
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

    当前余额3.43前往充值 >
    需支付:10.00
    成就一亿技术人!
    领取后你会自动成为博主和红包主的粉丝 规则
    hope_wisdom
    发出的红包
    实付
    使用余额支付
    点击重新获取
    扫码支付
    钱包余额 0

    抵扣说明:

    1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
    2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

    余额充值