• [UVa-437] Color Length


    Description

    给出两个字符串$a$,$b$,将他们穿插起来(相对位置不变),要求最小化$sum L(c)$,其中$L(c)$的定义时在穿插完的字符串中字符$c$的最大位置与最小位置的差。

    $n leq 5000$。

    Solution

    问题的转化

    这样的问题并不好用子问题来做,考虑最小化贡献。

    贡献是可以$DP$的。令$dp_{i,j}$表示将$a$的前$i$个与$b$的前$j$个合并后对答案的最优贡献。维护每个字母第一次出现的状态和最后一次出现的状态转移即可。

    /*By DennyQi 2019*/
    #include <cstdio>
    #include <queue>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    const int MAXN = 10010;
    const int MAXM = 20010;
    const int INF = 0x3f3f3f3f;
    inline int Max(const int a, const int b){ return (a > b) ? a : b; }
    inline int Min(const int a, const int b){ return (a < b) ? a : b; }
    inline int read(){
        int x = 0; int w = 1; register char c = getchar();
        for(; c ^ '-' && (c < '0' || c > '9'); c = getchar());
        if(c == '-') w = -1, c = getchar();
        for(; c >= '0' && c <= '9'; c = getchar()) x = (x<<3) + (x<<1) + c - '0'; return x * w;
    }
    int T,dp[5010],cnt[5010],lsta[30],lstb[30],fsta[30],fstb[30],la,lb;
    char a[5010],b[5010];
    inline void Init_cnt(){
        memset(lsta,0,sizeof(lsta));
        memset(lstb,0,sizeof(lstb));
        memset(fsta,0x3f,sizeof(fsta));
        memset(fstb,0x3f,sizeof(fstb));
        for(int i = 1; i <= la; ++i){
            lsta[a[i]-'A'] = max(lsta[a[i]-'A'],i);
            fsta[a[i]-'A'] = min(fsta[a[i]-'A'],i);
        }
        for(int i = 1; i <= lb; ++i){
            lstb[b[i]-'A'] = max(lstb[b[i]-'A'],i);
            fstb[b[i]-'A'] = min(fstb[b[i]-'A'],i);
        }
    }
    inline void DP(){
        memset(dp,INF,sizeof(dp));
        memset(cnt,0,sizeof(cnt));
        char cur;
        dp[0] = 0;
        for(int i = 0; i <= la; ++i){
            for(int j = 0; j <= lb; ++j){
                if(i==0 && j==0) continue;
                if(i == 0){    
                    cnt[j] = cnt[j-1];
                    cur = b[j]-'A';
                    if(j == fstb[cur]) ++cnt[j];
                    if(j == lstb[cur] && lsta[cur] == 0) --cnt[j];
                }
                else{
                    cur = a[i]-'A';
                    if(j >= lstb[cur] && i >= lsta[cur]) --cnt[j];
                    if(j < fstb[cur] && i == fsta[cur]) ++cnt[j];
                }
                dp[j] = min((j==0)?INF:dp[j-1], (i==0)?INF:dp[j])+cnt[j];
            }
        }
    }
    int main(){
        scanf("%d",&T);
        while(T--){
            scanf("%s%s",a+1,b+1);
            la = strlen(a+1), lb = strlen(b+1);
            Init_cnt();
            DP();
            printf("%d
    ",dp[lb]);
        }
        return 0;
    }
  • 相关阅读:
    jquery组件WebUploader文件上传用法详解
    asp.net Forms身份验证详解
    FormsAuthentication使用指南
    对于新手用c#中的delegate(委托)和event(事件)
    Union All/Union/Intersect操作
    DALFactory出现"未能加载文件或程序集“DAL”或它的某一个依赖项。系统找不到指定的文件”的解决方案 .
    C#多线程编程实例 线程与窗体交互
    FormsAuthentication使用指南
    asp.net Forms身份验证详解
    chrome浏览器调试JS代码
  • 原文地址:https://www.cnblogs.com/qixingzhi/p/10390174.html
Copyright © 2020-2023  润新知