zoukankan      html  css  js  c++  java
  • Uva 1625,颜色的长度

    类似于LCS的动态规划,指标函数的分解。

    题目链接:https://uva.onlinejudge.org/external/16/1625.pdf

    题目大意:两个颜色序列,将他们合并,合并的时候,每次都从开头拿颜色,对于每一个颜色c来说,都有他的跨度l(c),就是最后的位置与最前的位置的差值,就怎样的排列是的所有l(c)总和最小。

     

    分析:从两个串中随机拿字符,解答树是特别大的。

    d(i,j) p拿前 I 个字符, q拿前 j 个字符 所要的代价。

    n,m<=5000,二维数组改成滚动数组。

    这个时候,不是等到一个颜色全部移动玩了之后再算跨度。而是,只要多少种颜色已经开始但尚未结束,L(c) + 1;

    重点再与求代价C。首先计算全部移动Q,只要是该字符开头,代价就加一,但是如果刚好是最后一个就恢复。然后再推数组P时,就可以直接利用已经计算好的c代价数组,只需要根据他更新由于i的加入使得增加的代价。

    #include <bits/stdc++.h>
    using namespace std;
    
    #define maxn 5005
    #define INF 0x3f3f3f3f
    
    char p[maxn],q[maxn];
    int sp[26],ep[26],sq[26],eq[26];
    int d[2][maxn],c[2][maxn];
    
    int main()
    {
        int t;
        scanf("%d",&t);
        while(t--)
        {
            scanf("%s%s",p+1,q+1);
    
            int n = strlen(p+1);
            int m = strlen(q+1);
    
            for(int i=1; i<=n; i++) p[i] -='A';
            for(int i=1; i<=m; i++) q[i] -='A';
    
            for(int i=0; i<26; i++)
            {
                sp[i] = sq[i] = INF;
                ep[i] = eq[i] = 0;
            }
    
            for(int i=1; i<=n; i++)
            {
                sp[p[i]] = min(sp[p[i]],i);
                ep[p[i]] = i;
            }
    
            for(int i=1; i<=m; i++)
            {
                sq[q[i]] = min(sq[q[i]],i);
                eq[q[i]] = i;
            }
    
            memset(c,0,sizeof(c));
            memset(d,0,sizeof(d));
            int t = 1;
            //dp
            for(int i = 0; i <= n; i++)
            {
                for(int j = 0; j <= m; j++)
                {
                    if(!i && !j) continue;

    int v1 = INF, v2 = INF; if(i) v1 = d[t^1][j] + c[t^1][j]; // 从P上面移动 if(j) v2 = d[t][j - 1] + c[t][j - 1]; // 从Q上面移动 d[t][j] = min(v1, v2); // 更新代价 if(i) { c[t][j] = c[t^1][j]; if(sp[p[i]] == i && sq[p[i]] > j) c[t][j]++; if(ep[p[i]] == i && eq[p[i]] <= j) c[t][j]--; } else if(j) { c[t][j] = c[t][j - 1]; if(sq[q[j]] == j && sp[q[j]] > i) c[t][j]++; if(eq[q[j]] == j && ep[q[j]] <= i) c[t][j]--; } } t ^= 1; } printf("%d ", d[t^1][m]); } return 0; }

    两个颜色序列,将他们合并,合并的时候,每次都从开头拿颜色,对于每一个颜色c来说,都有他的跨度l(c),就是最后的位置与最前的位置的差值,就怎样的排列是的所有l(c)总和最小。

  • 相关阅读:
    emacs配置emacs-clang-complete-async
    emacs之配置自动安装脚本
    vim之YCM配置
    vim之vundle
    emacs之配置php
    kettle的日志
    kettle的报错解决机制
    kettle优化
    将BAT文件注册为服务的方法
    使用powerdesinger逆向生成表结构
  • 原文地址:https://www.cnblogs.com/TreeDream/p/5994374.html
Copyright © 2011-2022 走看看