zoukankan      html  css  js  c++  java
  • UVA 1625 Color Length DP

      题目链接: https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4500

      题目描述: 两个字符串 ,组成一个新的字符串, 每次只能从其中一个的开头选一个加到新的尾, 问l(i)的最小值

      解题思路: dp(i, j)  表示从第一个字符串中取i 个, 第二个字符串中取j个时的最优方案, 我们创建数组c 表示从第一个字符串中取i 个, 第二个字符串中取j个时开始还没有结束的字符的数量, 这样状态转移方程就可以写成: dp(i,j) = min(dp(i-1,j)+c[i-1,j], dp(i, j-1)+c[i,j-1]) 我们每做一次状态转移就更新一次c数组

      代码: 

    #include <iostream>
    #include <cstdio>
    #include <string>
    #include <vector>
    #include <map>
    #include <cstring>
    #include <iterator>
    #include <cmath>
    #include <algorithm>
    #include <stack>
    #include <deque>
    #include <map>
    
    #define lson l, m, rt<<1
    #define rson m+1, r, rt<<1|1
    typedef long long LL;
    using namespace std;
    const int maxn = 5000+5;
    
    int dp[maxn][maxn];  // dp(i,j) p中取i个, q中取j个的最小代价
    char p[maxn];
    char q[maxn];
    int c[maxn][maxn]; // c(i,j) p中取i个, q中取j个已经开始还没有结束字符的个数
    int sp[30], sq[30], ep[30], eq[30];
    const int INF = 0x3fffffff;
    
    int main() {
        int t;
        scanf( "%d", &t );
        while( t-- ) {
    //        scanf( "%s", p+1);
    //        scanf( "%s", q+1);
            scanf("%s%s", p + 1, q + 1);
            int n = (int)strlen(p+1);
            int m = (int)strlen(q+1);
            memset(c, 0, sizeof(c));
            memset(dp, 0, sizeof(dp));
            
            for( int i = 1; i <= n; i++ ) p[i] -= 65;
            for( int j = 1; j <= m; j++ ) q[j] -= 65;
            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;
            }
            for( int i = 0; i <= n; i++ ) {
                for( int j = 0; j <= m; j++ ) {
                    if( !i && !j ) continue;
                    int v1, v2;
                    v1 = v2 = INF;
                    if( i ) v1 = dp[i-1][j] + c[i-1][j];
                    if( j ) v2 = dp[i][j-1] + c[i][j-1];
                    dp[i][j] = min( v1, v2 );
                    if( i ) {
                        c[i][j] = c[i-1][j];
    //                    if( sp[p[i]] == i && (ep[p[i]] > i || eq[p[i]] > j ) ) c[i][j]++;
    //                    if( ep[p[i]] == i && eq[p[i]] <= j ) c[i][j]--;
                        if (sp[p[i]] == i && sq[p[i]] > j)  c[i][j]++;
                        if (ep[p[i]] == i && eq[p[i]] <= j) c[i][j]--;
                    }
                    else if( j ) {
                        c[i][j] = c[i][j-1];
    //                    if( sq[q[j]] == j && (eq[q[j]] > j || ep[q[j]] > i ) ) c[i][j]++;
    //                    if( eq[q[j]] == j && ep[q[j]] <= i ) c[i][j]--;
                        if (sq[q[j]] == j && sp[q[j]] > i)  c[i][j]++;
                        if (eq[q[j]] == j && ep[q[j]] <= i) c[i][j]--;
                    }
                }
            }
            printf( "%d
    ", dp[n][m] );
        }
        return 0;
    }
    View Code

      思考:状态转移时, 要注意和状态转移有关的变量有哪几个, 是否能够从原条件中预处理出来, 如果能够预处理出来就去做, 否则就换状态

  • 相关阅读:
    高阶函数 map
    高阶函数_filter
    sort和sorted方法的使用
    一个函数作为另外一个函数的参数
    匿名函数
    jenkins+Xcode+蒲公英实现ipa自动打包发布全攻略
    iOS 画贝塞尔曲线 连续曲线 平滑曲线 曲线图表
    基于WebRTC实现iOS端音频降噪功能
    苹果ios音频的回声消除处理
    iOS实现录音功能
  • 原文地址:https://www.cnblogs.com/FriskyPuppy/p/7323400.html
Copyright © 2011-2022 走看看