• CF10D LCIS[动态规划]


    LCISLCIS


    Description

    链接
    给出两个长度分别为N,MN, M的数列, 求最长上升公共子序列的长度


    Solution

    设阶段为 i,ji, j 表示第一个串前ii个元素与第二个串前jj个元素 LCISLCIS
    根据LCSLCS的转移方程, 初步得出 :

    if(Ai==Bi)if(A_i == B_i). dp[i,j]=dp[i1][j1]+1dp[i, j] = dp[i-1][j-1] + 1
    elseelse. dp[i,j]=max(dp[i1][j],dp[i][j1])dp[i, j] = max(dp[i-1][j], dp[i][j-1])

    但这是错误的, 因为还要求单调递增, 于是为了方便转移, 需要额外一个维度来保证正确性?
    dp[i,j,k]dp[i, j, k] 表示第一个串前ii项与第二个串前jjLCISLCIS且最后一个元素为 kk
    可以初步得到

    if(Ai==Bj)if(A_i == B_j). dp[i,j,Bj]=dp[i1,j1,Bp]+1dp[i, j, B_j] = dp[i-1, j-1, B_p]+1. {p(0,j),Bp<k}{p∈(0, j), B_p <k}
    elseelse. dp[i,j,k]=dp[i1,j,k]dp[i, j, k] = dp[i-1, j, k]

    然而上方的愚蠢行为不知道会引起多少人笑话…
    完全可以不要第3维:

    if(Ai==Bj)if(A_i == B_j). dp[i,j]=dp[i1,p]+1dp[i, j] = dp[i-1, p]+1. {p(0,j),Bp<k}{p∈(0, j), B_p <k}
    elseelse. dp[i,j]=dp[i,j1]dp[i, j] = dp[i, j-1]

    由于最后要输出方案, 所以使用PrePre数组记录最优转移来源, 最后递归输出即可


    Code

    #include<bits/stdc++.h>
    #define reg register
    
    const int maxn = 505;
    
    int N;
    int M;
    int A[maxn];
    int B[maxn];
    int dp[maxn][maxn];
    int Pre[maxn][maxn];
    
    void print(int x){
            if(!x) return ;
            print(Pre[N][x]);
            printf("%d ", B[x]);
    }
    
    int main(){
            scanf("%d", &N);
            for(reg int i = 1; i <= N; i ++) scanf("%d", &A[i]);
            scanf("%d", &M);
            for(reg int i = 1; i <= M; i ++) scanf("%d", &B[i]);
            for(reg int i = 1; i <= N; i ++){
                    int maxx = 0, pre = 0;
                    for(reg int j = 1; j <= M; j ++){
                            if(A[i] == B[j]){
                                    if(dp[i][j] < maxx + 1){
                                            dp[i][j] = maxx + 1;
                                            Pre[i][j] = pre;
                                    }
                            }
                            else{
                                    dp[i][j] = dp[i-1][j];
                                    Pre[i][j] = Pre[i-1][j];
                            }
                            if(B[j] < A[i] && maxx < dp[i-1][j]) maxx = dp[i-1][j], pre = j;
                    }
            }
            int Ans = 0, Ans_p = 0;
            for(reg int i= 1; i <= M; i ++)
                    if(Ans < dp[N][i]) Ans = dp[N][i], Ans_p = i;
            printf("%d
    ", Ans);
            print(Ans_p);
            return 0;
    }
    
  • 相关阅读:
    sql经典语句大全
    经典SQL语句大全
    Bat命令学习
    [Microsoft][ODBC 驱动程序管理器] 在指定的 DSN 中,驱动程序和应用程序之间的体系结构不匹配
    配置WebSite的IIS时遇到的问题与解决方法
    数据库SQL优化大总结之 百万级数据库优化方案
    数据库索引以及优化
    搭建android开发环境
    SQL2008根据日志恢复
    WebService处理大数据量数据
  • 原文地址:https://www.cnblogs.com/zbr162/p/11822655.html
Copyright © 2020-2023  润新知