UVa1625 Color Length

UVa1625 - Vjudge

  • 题目大意:
    将两个颜色序列按照顺序合并成一个序列,使每种颜色的最大位置和最小位置之差的和最小。
  • 题解:
    f[i][j]表示两个序列分别移走了i和j个元素,还需要多少费用。记录已经开始但是还未结束的颜色的数量为tmp,则f[i][j] = tmp + min( f[i-1][j], f[i][j-1] )。tmp可以通过预处理每个颜色在两个序列中的开始位置和结束位置得到。
// UVa 1625 By KikiDMW
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#define ll long long
using namespace std;
const int N = 5000 + 10, L = 30, inf = 0x3f3f3f3f;

int f[N][N], c[N][N], t, n, m;
int sta[L], stb[L], eda[L], edb[L];
char s1[N], s2[N];

inline void in(int &ret);
inline void in(ll &ret);

void init(){
    scanf("%s%s", s1+1, s2+1);
    for(int i = 0; i < 26; i++) sta[i] = stb[i] = inf, eda[i] = edb[i] = -inf;
}
void work(){
    while(t--){
        init();
        n = strlen(s1+1); m = strlen(s2+1);
        for(int i = 1; i <= n; i++){
            if(sta[s1[i]-'A'] == inf) sta[s1[i]-'A'] = i;
            eda[s1[i]-'A'] = i;
        }
        for(int i = 1; i <= m; i++){
            if(stb[s2[i]-'A'] == inf) stb[s2[i]-'A'] = i;
            edb[s2[i]-'A'] = i;
        }
        for(int i = 1; i <= n+1; i++){
            for(int j = 1; j <= m+1; j++){
                f[i][j] = 0;
                for(int k = 0; k < 26; k++)
                    if((sta[k] < i || stb[k] < j) && (i <= eda[k] || j <= edb[k])) 
                        f[i][j]++;
                if(i == 1 && j == 1) continue;
                else if(j == 1) f[i][j] += f[i-1][j];
                else if(i == 1) f[i][j] += f[i][j-1];
                else f[i][j] += min(f[i-1][j], f[i][j-1]);
            }
        }
        printf("%d\n", f[n+1][m+1]);
    }
}

int main(){
    in(t);
    work();
    return 0;
}
inline void in(int &ret){
    ret = 0; int f = 1; char ch; ch = getchar();
    while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar(); }
    while(ch >= '0' && ch <= '9'){ ret = ret * 10 + ch - '0'; ch = getchar(); }
    ret *= f;
}
inline void in(ll &ret){
    ret = 0; ll f = 1; char ch; ch = getchar();
    while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar(); }
    while(ch >= '0' && ch <= '9'){ ret = ret * 10 + ch - '0'; ch = getchar(); }
    ret *= f;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值