uva 11552 dp

UVA 11552 - Fewest Flops

一个字符串,字符串每 k 个当作一组,组中的字符顺序可以重组。问经过重组后改字符串可以编程最少由多少块字符组成。连续的一段字符被称为块。

dp[i][j] 表式第i组以字符j结尾的最少块数。
那么我们考虑添加一组后可以减少块数的情况。
1):上一组的结尾在这一组里找得到同样的字符,并且该字符不作为当前块的结尾。如果要作为结尾的话要把该字符所在的块拆开,所以然并卵。
2):当前组只有一种字符,并且和上一组的结尾相同。

这两种情况都可以使块数减一

dp[i][s] = min(dp[i-1][t] + cnt[i] - flag);flag表示是否满足上述两种情况。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int INF = 999999999;

char s[1005];

int c[1005][26];
int dp[1005][26];
int _cnt[1005];
int k, len;

int main() { // freopen("out.txt", "w", stdout);
    int Tcase;
    scanf ("%d", &Tcase);
    for (; Tcase>0; --Tcase) {
        scanf ("%d%s", &k, s);
        len = strlen(s);

        int _c=-1;
        memset(c, 0, sizeof(c));
        memset(_cnt, 0, sizeof(_cnt));
        while (_c<len/k) {
            for (int j=0; j<k; j++) {
                if (c[_c][s[_c*k+j]-'a'] == 0) _cnt[_c]++;
                c[_c][s[_c*k+j]-'a']++;
            }
            _c++;
        }


        for (int i=0; i<=_c; i++) {
            for(int j=0; j<26; j++) {
                dp[i][j] = INF;
            }
        }

        for (int i=0; i<26; i++) {
            if (c[0][i] != 0) dp[0][i] = _cnt[0];
            else dp[0][i] = INF;
        }

        for (int i=1; i<_c; i++) {
            for (int s=0; s<26; s++) {
                for (int t=0; t<26; t++) {
                    if (c[i][s] == 0) continue;
                    if (c[i-1][t] == 0) continue;

                    if (c[i][t] != 0 && (_cnt[i] == 1 || s != t)) {
                        dp[i][s] = min(dp[i][s], dp[i-1][t] + _cnt[i] - 1);// cout << s << " " << t << endl;
                    } else {
                        dp[i][s] = min(dp[i][s], dp[i-1][t] + _cnt[i]);
                    }
                }
            }
        }


        int ans = INF;
        for (int i=0; i<26; i++) {
            ans = min(ans, dp[_c-1][i]);
        }
        printf ("%d\n", ans);
    }

    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值