UVA 1625 Color Length

Problem Description

这里写图片描述

输入两个颜色序列,要求按顺序合并成一个序列,即每次把一个序列的开头的颜色放到新序列的尾部。对于每个颜色c来说,其跨度l(c),表示c的最大位置和最小位置的差。

你的任务是找一种合并方式使得所有l(c)的总和最小。dp[i][j]表示第一个串移走了i个元素,第二个串移走了j个元素还需要多少费用。

dp[i][j]表示的是,当序列1取了i个,序列2取了j个时,对“已经出现,但还没有结束的颜色”的影响

普通的状态转移比较麻烦,要考虑每个颜色上一次出现的位置。我们换一种思路,不是等到一个颜色转移之后再计算,而是每一次累加,当把一个颜色移到最终序列前,把所有已经出现但是没有结束的颜色的l(c)加一。进一步,不需要关注每个颜色的l(c),只需要知道多少种颜色已经开始但是没有结束。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<vector>
#include<stack>
#include<set>
#include<map>
#include<queue>
#include<algorithm>
using namespace std;
char a[5005],b[5005];
int dp[5005][5005];
int starta[26],enda[26],startb[26],endb[26];
int main(){
    int kase;
    scanf("%d",&kase);
    int lena,lenb;
    int i,j,k;
    while(kase--){
        scanf("%s",a);
        scanf("%s",b);
        lena=strlen(a);
        lenb=strlen(b);
        for(i=0;i<26;i++){
            starta[i]=99999999;
            startb[i]=99999999;
            enda[i]=-99999999;
            endb[i]=-99999999;
        }
        for(i=0;i<lena;i++){
                a[i]-='A';
            if(starta[a[i]]==99999999){
                starta[a[i]]=i+1;
            }
            enda[a[i]]=i+1;
        }
        for(i=0;i<lenb;i++){
                b[i]-='A';
            if(startb[b[i]]==99999999){
                startb[b[i]]=i+1;
            }
            endb[b[i]]=i+1;
        }
        for(i=0;i<=lena;i++){
            for(j=0;j<=lenb;j++){
                dp[i][j]=0;
                for(k=0;k<26;k++){
                    if((i>=starta[k]||j>=startb[k])&&(i<enda[k]||j<endb[k]))
                        dp[i][j]++;
                }
                if(i==0&&j==0)
                    continue;
                else if(i==0)
                    dp[i][j]+=dp[i][j-1];
                else if(j==0)
                    dp[i][j]+=dp[i-1][j];
                else
                    dp[i][j]+=min(dp[i-1][j],dp[i][j-1]);
            }
        }
        printf("%d\n",dp[lena][lenb]);
    }
    return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值