• UVa 1625 Color Length


    思路还算明白,不过要落实到代码上还真敲不出来。

    题意:

    有两个由大写字母组成的颜色序列,将它们合并成一个序列:每次可以把其中一个序列开头的颜色放到新序列的尾部。

    对于每种颜色,其跨度定义为合并后的序列中最后一次和第一次出现的位置之差,求所有合并方案中所有颜色跨度之和的最小值。

    分析:

    d(i, j)表示两个串分别已经移走了i个和j个字符。那么无论新串的顺序是什么,有多少种颜色已经开始但尚未结束是确定的,记为c(i, j)。再继续移走一个字符,所有颜色跨度之和就增加c(i, j)。c的计算是通过记录每种颜色在每个串的始末位置来确定的。

    由于数据量较大,还用滚动数组来优化空间复杂度。

     1 //#define LOCAL
     2 #include <iostream>
     3 #include <cstdio>
     4 #include <cstring>
     5 #include <algorithm>
     6 using namespace std;
     7 
     8 const int maxn = 5000 + 10;
     9 const int INF = 1000000000;
    10 char p[maxn], q[maxn];
    11 int sp[26], ep[26], sq[26], eq[26];    //记录两个串每种颜色的始末
    12 int d[2][maxn], c[2][maxn];    //c[i][j]表示d[i][j]时还有多少种颜色已经开始但尚未结束
    13 
    14 int main(void)
    15 {
    16     #ifdef LOCAL
    17         freopen("1625in.txt", "r", stdin);
    18     #endif
    19 
    20     int n, m, T;
    21     scanf("%d", &T);
    22     while(T--)
    23     {
    24         scanf("%s", p+1);
    25         scanf("%s", q+1);
    26         n = strlen(p+1);
    27         m = strlen(q+1);
    28         for(int i = 1; i <= n; ++i)    p[i] -= 'A';
    29         for(int i = 1; i <= m; ++i)    q[i] -= 'A';
    30 
    31         for(int i = 0; i < 26; ++i)    { sp[i] = sq[i] = INF; ep[i] = eq[i] = 0; }
    32         for(int i = 1; i <= n; ++i)
    33         {
    34             sp[p[i]] = min(sp[p[i]], i);
    35             ep[p[i]] = i;
    36         }
    37         for(int i = 1; i <= m; ++i)
    38         {
    39             sq[q[i]] = min(sq[q[i]], i);
    40             eq[q[i]] = i;
    41         }
    42 
    43         int t = 0;
    44         memset(d, 0, sizeof(d));
    45         memset(c, 0, sizeof(c));
    46         for(int i = 0; i <= n; ++i)
    47         {
    48             for(int j = 0; j <= m; ++j)
    49             {
    50                 if(!i && !j)    continue;
    51 
    52                 int v1, v2;
    53                 v1 = v2 = INF;
    54                 if(i)    v1 = d[t^1][j] + c[t^1][j];
    55                 if(j)    v2 = d[t][j-1] + c[t][j-1];
    56                 d[t][j] = min(v1, v2);
    57                 //计算c
    58                 if(i)
    59                 {
    60                     c[t][j] = c[t^1][j];
    61                     if(sp[p[i]] == i && sq[p[i]] > j)    c[t][j]++;
    62                     if(ep[p[i]] == i && eq[p[i]] <= j)    c[t][j]--;
    63                 }
    64                 else if(j)
    65                 {
    66                     c[t][j] = c[t][j-1];
    67                     if(sq[q[j]] == j && sp[q[j]] > i)    c[t][j]++;
    68                     if(eq[q[j]] == j && ep[q[j]] <= i)    c[t][j]--;
    69                 }
    70             }
    71             t ^= 1;
    72         }
    73         printf("%d
    ", d[t^1][m]);
    74     }
    75 
    76     return 0;
    77 }
    代码君
  • 相关阅读:
    多态
    课堂动手动脑
    凯撒加密
    构造方法、类初始化
    课堂动手动脑------随机数的产生
    课堂内容小结
    JAVA数字求和
    运行上次失败用例(--lf 和 --ff)
    conftest.py作用范围
    fixture作用范围
  • 原文地址:https://www.cnblogs.com/AOQNRMGYXLMV/p/4006498.html
Copyright © 2020-2023  润新知