• 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;
    }
    
  • 相关阅读:
    node
    github
    [模块] pdf转图片-pdf2image
    python 15 自定义模块 随机数 时间模块
    python 14 装饰器
    python 13 内置函数II 匿名函数 闭包
    python 12 生成器 列表推导式 内置函数I
    python 11 函数名 迭代器
    python 10 形参角度 名称空间 加载顺序
    python 09 函数参数初识
  • 原文地址:https://www.cnblogs.com/zbr162/p/11822655.html
Copyright © 2020-2023  润新知