• Color Length UVA


    题目大意:

    给你两个字符串p,q,字符串中每个字符代表一个颜色,现在按顺序合并两个字符串,得到一个新字符串。新字符串的价值为,每个颜色价值的和,单个颜色价值的和等于该颜色在新字符中最后一次出现的位置减去第一次出现的位置。求最小价值

    题目思路:

    dp[i][j]代表使用p的前i个字符,q的前j个字符合并产生的价值。对于dp[i][j],可由dp[i-1][j],dp[i][j-1]转移得到,每次转移增加的价值为【已被填入,但尚未填完的颜色的个数】。

    用c[][]维护当前已被填入但尚未被填完的颜色的数目,若一个颜色新加入就加一,若一个颜色被填完就减一。

    由于dp[5000][5000]太大了,且每次转移仅与dp[i-1][j],dp[i][j-1]有关,我们可以采用滚动数组优化

    #pragma GCC optimize(2)
    #include<stdio.h>
    #include<algorithm>
    #include<string.h>
    #include<stdlib.h>
    #include<iostream>
    #include<stack>
    #include<vector>
    #include<math.h>
    using namespace std;
    #define LL long long
    #define INF 0x3f3f3f3f
    
    int dp[2][5001];
    int c[2][5001];
    char s1[5005],s2[5005];
    struct node
    {
        int s,e;
    } p1[30],p2[30];
    
    int main()
    {
        int n;
        scanf("%d",&n);
        //cout << (int) 'Y'-'A' << endl;
        while(n--)
        {
            for(int i=0; i<26; i++)
            {
                p1[i].s = p2[i].s = INF;
                p1[i].e = p2[i].e = -1;
            }
            scanf("%s",s1+1);
            scanf("%s",s2+1);
            int l1 = strlen(s1+1);
            int l2 = strlen(s2+1);
            for(int i=1; i<=l1; i++)
            {
                int id = s1[i] - 'A';
                if(p1[id].s == INF)
                    p1[id].s = i;
                p1[id].e = i;
            }
            for(int i=1; i<=l2; i++)
            {
                int id = s2[i] - 'A';
                if(p2[id].s == INF)
                    p2[id].s = i;
                p2[id].e = i;
            }
            int t = 0;
            memset(c,0,sizeof(c));
            memset(dp,0,sizeof(dp));
            for(int i=0; i<=l1; i++)
            {
                for(int j=0; j<=l2; j++)
                {
                    if(!i && !j)
                        continue;
                    int v1=INF,v2=INF;
                    if(i)
                        v1 = dp[t^1][j] + c[t^1][j];
                    if(j)
                        v2 = dp[t][j-1] + c[t][j-1];
                    dp[t][j] = min(v1,v2);
    
                    if(i)
                    {
                        c[t][j] = c[t^1][j];
                        if(p1[s1[i]-'A'].s == i && p2[s1[i]-'A'].s>j)
                            c[t][j]++;
                        if(p1[s1[i]-'A'].e == i && p2[s1[i]-'A'].e <= j)
                            c[t][j]--;
                    }
                    if(j)
                    {
                        c[t][j] = c[t][j-1];
                        if(p2[s2[j]-'A'].s == j && p1[s2[j]-'A'].s>i)
                            c[t][j]++;
                        if(p2[s2[j]-'A'].e == j && p1[s2[j]-'A'].e <= i)
                            c[t][j]--;
                    }
                }
                t ^= 1;
            }
            printf("%d
    ",dp[t^1][l2]);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    ionic2 开始第一个App(二)
    简单的文件下载方法
    php获取汉字首字母
    LumiSoft.Net邮件接收乱码问题解决
    输入框字符限制插件·
    微软相关产品集合的网站,感觉找软件很方便 也很全 收藏了
    利用发射 下拉列表绑定枚举
    ASP.NET中UpdatePanel内控件的JS失效的问题
    Json格式转string
    SQL 判断是否存在时间交叉
  • 原文地址:https://www.cnblogs.com/alan-W/p/10800109.html
Copyright © 2020-2023  润新知