zoukankan      html  css  js  c++  java
  • 【Uva 1625】Color Length

    Link:

    Description

    给你两个序列,都由大写字母组成;
    每次,把两个序列中的一个的开头字母加在字符串的尾端,然后在那个序列中删掉那个开头字母;
    最后得到一个字符串;
    这个字符串显然后很多种;
    让你找所有字母的L(C)的和的最小值;
    L(c)是某个字母在最后的那个字符串中出现的结尾位置和开始位置的差值;

    Solution

    设f[i][j]表示第一个序列1..i全都移除掉了,第二个序列1..j全都移除掉了的最小L(c)和;
    这里不能直接算出某个字母的L(C)值,但是能一步一步地累加,比如,你新加了一个字母x,然后在此之前,已有的字符串里面,有字母a,且还有未加入的字母a;
    则L(a)的值可以肯定会递增1了;
    则可以写出转移方程
    f[i][j]=min(f[i][j],f[i1][j]+cnt[i1][j])
    f[i][j]=min(f[i][j],f[i][j1]+cnt[i][j1]);
    这里的cnt[i][j]表示第一个序列前i个字母移出去了,第二个序列前j个字母移出去了所形成的字符串,有多少个字母已经出现了,但是还没有全部出现;
    为了获取这个cnt数组;
    可以先获取,每个字母在这两个序列中第一次出现最后一次出现的位置;
    然后对于枚举的i和j;
    看看每个字母是不是在这个情况下出现了;
    这样就能获得cnt数组;

    NumberOf WA

    4

    Reviw

    用memset会莫名的TLE;
    改成循环就过了

    Code

    #include <bits/stdc++.h>
    using namespace std;
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define LL long long
    #define rep1(i,a,b) for (int i = a;i <= b;i++)
    #define rep2(i,a,b) for (int i = a;i >= b;i--)
    #define mp make_pair
    #define pb push_back
    #define fi first
    #define se second
    #define ms(x,y) memset(x,y,sizeof x)
    #define Open() freopen("F:\rush.txt","r",stdin)
    #define Close() ios::sync_with_stdio(0)
    
    typedef pair<int,int> pii;
    typedef pair<LL,LL> pll;
    
    const int dx[9] = {0,1,-1,0,0,-1,-1,1,1};
    const int dy[9] = {0,0,0,-1,1,-1,1,-1,1};
    const double pi = acos(-1.0);
    const int N = 5e3;
    const int INF = 0x3f3f3f3f;
    
    int dp[N+100][N+100],n,m,cnt[N+100][N+100];
    pii a1[27],a2[27];
    char s1[N+100],s2[N+100];
    
    int main(){
        //Open();
        //Close();
        int T;
        scanf("%d",&T);
        while (T--){
            scanf("%s",s1+1);
            scanf("%s",s2+1);
            n = strlen(s1+1),m = strlen(s2+1);
    
            rep1(i,1,26) a1[i].fi = a1[i].se = a2[i].fi = a2[i].se = 0;
    
            //第一次出现
            rep1(i,1,n){
                int t = s1[i]-'A'+1;
                if (a1[t].fi==0) a1[t].fi = i;
            }
            rep1(i,1,m){
                int t = s2[i]-'A'+1;
                if (a2[t].fi==0) a2[t].fi = i;
            }
    
            //最后一次出现
            rep2(i,n,1){
                int t = s1[i]-'A'+1;
                if (a1[t].se==0) a1[t].se = i;
            }
            rep2(i,m,1){
                int t = s2[i]-'A'+1;
                if (a2[t].se==0) a2[t].se = i;
            }
            rep1(i,0,n)
                rep1(j,0,m){
                    int temp = 26;
                    rep1(k,1,26){
                        if (a1[k].fi == 0 && a2[k].fi==0){
                            temp--;
                            continue;
                        }
                        if (a1[k].fi!=0 && a2[k].se==0){
                            if (i<a1[k].fi){
                                temp--;
                                continue;
                            }
                            if (a1[k].se<=i){
                                temp--;
                                continue;
                            }
                        }
                        if (a1[k].fi==0 && a2[k].se!=0){
                            if (j<a2[k].fi){
                                temp--;
                                continue;
                            }
                            if (a2[k].se<=j){
                                temp--;
                                continue;
                            }
                        }
                        if (a1[k].fi!=0 && a2[k].fi!=0){
                            if (i<a1[k].fi && j<a2[k].fi){
                                temp--;
                                continue;
                            }
                            if (a1[k].se<=i && a2[k].se<=j){
                                temp--;
                                continue;
                            }
                        }
                    }
                    cnt[i][j] = temp;
                }
            rep1(i,0,n)
                rep1(j,0,m)
                    dp[i][j] = INF;
            dp[0][0] = 0;
            rep1(i,0,n)
                rep1(j,0,m){
                        if (i-1 >= 0){
                            dp[i][j] = min(dp[i][j],dp[i-1][j] + cnt[i-1][j]);
                        }
                        if (j-1 >= 0){
                            dp[i][j] = min(dp[i][j],dp[i][j-1] + cnt[i][j-1]);
                        }
                    }
            cout << dp[n][m] << endl;
        }
        return 0;
    }
    
  • 相关阅读:
    socket网络编程
    Oracle 分区表 总结
    修改配置文件后不重启程序即时生效
    vue 计算属性
    Vue属性绑定指令 vbind
    vue虚拟dom
    vueslot插槽
    将博客搬至CSDN
    打造山寨手机中的App Store斯凯MiniJ(mrp)诞生记
    【教程】查看某个程序的占用的端口
  • 原文地址:https://www.cnblogs.com/AWCXV/p/7626202.html
Copyright © 2011-2022 走看看