UVA - 1625 Color Length

题目链接

你有两个序列,每个序列都由颜色的缩写组成(如RRRGGGBBBBBBB),现在通过每次挑一个序列,把序列中首位的颜色提出来放到新序列的尾部,把两个序列合成一个序列。设L(c)是颜色c最右位置和最左位置的差,求所有L和的最小值。

当一个颜色c被放入新序列而没有结束(原序列中还有该颜色)时,每次放入一个颜色Lc就要加一。所以只要知道有多少个颜色还没有结束,然后加就行了。

AC代码:

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

using namespace std;

typedef long long LL;
const int maxn=5010, INF=0x3f3f3f3f;

int n,m;
char a[maxn],b[maxn];
int d[maxn][maxn],bg[30][2],ed[30][2],w[maxn][maxn];

void dp()
{
    memset(bg,0,sizeof(bg));
    memset(ed,0,sizeof(ed));
    for(int i=0;i<26;i++)
        bg[i][0]=bg[i][1]=INF;
    for(int i=1;i<=n;i++)
    {
        int c=a[i]-'A';
        if(bg[c][0]==INF)
            bg[c][0]=i;
        ed[c][0]=i;
    }

    for(int i=1;i<=m;i++)
    {
        int c=b[i]-'A';
        if(bg[c][1]==INF)
            bg[c][1]=i;
        ed[c][1]=i;
    }

    for(int i=0;i<=n;i++)
        for(int j=0;j<=m;j++)
    {
        if(i==0&&j==0)
            continue;
        int t1=INF,t2=INF;

        if(i>0)
            t1=d[i-1][j]+w[i-1][j];
        if(j>0)
            t2=d[i][j-1]+w[i][j-1];
        d[i][j]=min(t1,t2);

        if(i>0)
            {
                w[i][j]=w[i-1][j];
                int c=a[i]-'A';
                if(bg[c][0]==i&&bg[c][1]>j) w[i][j]++;
                if(ed[c][0]==i&&ed[c][1]<=j) w[i][j]--;
            }
        else
        {
            w[i][j]=w[i][j-1];
            int c=b[j]-'A';
            if(bg[c][1]==j&&bg[c][0]>i) w[i][j]++;
            if(ed[c][1]==j&&ed[c][0]<=i) w[i][j]--;
        }
    }
}
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        scanf("%s%s",a+1,b+1);
        n=strlen(a+1),m=strlen(b+1);
        dp();
        cout<<d[n][m]<<endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41333002/article/details/82152720