UVA 11552 Fewest Flops——dp

版权声明:欢迎大家转载,转载请注明出处 https://blog.csdn.net/hao_zong_yin/article/details/82023386

注意当前块结尾字符若等于前一个块的结尾字符,要判一下当前块的字符总数是否为1

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 1010;
const int INF = 0x3f3f3f3f;
int T, k;
char s[maxn];
struct Block {
    int cnt;
    bool c[26];
}a[maxn];
int dp[maxn][26]; //递推到第i块,当前块以字符j为结尾的最小答案
void solve() {
    scanf("%d", &k);
    scanf("%s", s);
    int n = strlen(s);
    for (int i = 0; i < n; i++) {
        a[i].cnt = 0;
        for (int j = 0; j < 26; j++) a[i].c[j] = 0;
    }
    for (int i = 0; s[i]; i += k) {
        for (int j = 0; j < k; j++) {
            a[i/k].c[s[i+j]-'a'] = 1;
        }
        for (int j = 0; j < 26; j++) if (a[i/k].c[j]) a[i/k].cnt++;
    }
    n = n / k;
//    cout << "  ";
//    for (int i = 0; i < 26; i++) cout << (char)(i+'a') << " ";
//    cout << endl;
//    for (int i = 0; i < n; i++) {
//        cout << a[i].cnt << ":";
//        for (int j = 0; j < 26; j++) cout << a[i].c[j] << " ";
//        cout << endl;
//    }
    for (int i = 0; i < n; i++) for (int j = 0; j < 26; j++) dp[i][j] = INF;
    for (int j = 0; j < 26; j++) dp[0][j] = a[0].cnt;
    for (int i = 1; i < n; i++) {
        for (int j = 0; j < 26; j++) {
            if (!a[i].c[j]) continue;
            for (int k = 0; k < 26; k++) {
                if (!a[i-1].c[k]) continue;
                if (a[i].c[k]) {
                    if (k == j) dp[i][j] = min(dp[i][j], dp[i-1][k] + a[i].cnt - (a[i].cnt == 1));
                    else dp[i][j] = min(dp[i][j], dp[i-1][k] + a[i].cnt - a[i].c[k]);
                }
                else dp[i][j] = min(dp[i][j], dp[i-1][k] + a[i].cnt - a[i].c[k]);
            }
        }
    }
    int ans = INF;
    for (int j = 0; j < 26; j++) ans = min(ans, dp[n-1][j]);
    printf("%d\n", ans);
}
int main() {
    scanf("%d", &T);
    while (T--) solve();
    return 0;
}

猜你喜欢

转载自blog.csdn.net/hao_zong_yin/article/details/82023386