zoukankan      html  css  js  c++  java
  • LCIS(最长公共上升子序列)

    LCIS(最长公共上升子序列)

    方案输出+dp储存最优值优化

    分析:

    这道题明显是将LCS和LIS结合,那么可以想到(我没想到定义dp[ i ] [ j ]是a中1~i 和 b中1~j 以 b[ j ] 结尾的最长LCIS长度。

    转移:当a[ i ]==b[ j ]时,要在小于j中找到一个最大的dp[i-1][k]并满足b[k]<a[i] || b[k]<b[j] (因为此时a[i]==b[j],要满足上升)

    优化:枚举这个k会使时间复杂度到n^3级别,所以用储存最优值的方法优化

    这是没有优化的原代码

    for(int i=1;i<=n;i++)
         for(int j=1;j<=m;j++){
             if(a[i]!=b[j]) dp[i][j]=dp[i-1][j];
             else{
                 for(int k=1;k<j;k++)
                 if(b[k]<a[i])//a[i]==b[j]
                dp[i][j]=max(dp[i][j],dp[i-1][k]+1);
            }

    优化后完整代码

    //方案输出+储存最优值优化 
    #include<bits/stdc++.h>
    using namespace std;
    #define N 505
    int n,m,a[N],b[N],dp[N][N],path[N][N];
    void dfs(int now,int p)
    {
        if(now==0) return ;
        dfs(now-1,path[now][p]);//now是现在输出到第几个了  
        if(p!=path[now][p])
        printf("%d ",b[p]);
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        scanf("%d",&m);
        for(int i=1;i<=m;i++) scanf("%d",&b[i]);
        //没有优化的dp转移 
        /*for(int i=1;i<=n;i++)
         for(int j=1;j<=m;j++){
             if(a[i]!=b[j]) dp[i][j]=dp[i-1][j];
             else{
                 for(int k=1;k<j;k++)
                 if(b[k]<a[i])//a[i]==b[j]
                dp[i][j]=max(dp[i][j],dp[i-1][k]+1);
            }
        }*/
        //优化:储存最优值:每次用一个临时变量储存一下最优值 更新的时候直接用 而不是for一遍寻找 
        //当更新完一个dp 又将最优值更新  适用范围:决策集合只增不减 
        for(int i=1;i<=n;i++){
            int k=0;//k==0!! k=j-1 k的初始值一定是0!! 因为从上面未优化中可知 k的范围是:1~j-1 而 j第一次是 1 
             for(int j=1;j<=m;j++){
                 if(a[i]!=b[j]) 
                  dp[i][j]=dp[i-1][j] ,path[i][j]=j;//路径输出:每次记录一下 填的这个数在b数组中的下标 然后递归输出 
                 else 
                  dp[i][j]=dp[i-1][k]+1 ,path[i][j]=k;
                //满足单调递增的条件 且j比 k优 
                if( b[j]<a[i] && dp[i-1][j]>dp[i-1][k] ) k=j;//当dp被更新后 将临时变量更新一下 
            }
        }
        int ans=0,pos;
        for(int i=1;i<=m;i++)
        if(dp[n][i]>ans)
         ans=dp[n][i],pos=i;
        printf("%d
    ",ans);
        if(ans) 
        dfs(n,pos);
    }
  • 相关阅读:
    Supreme(ง •̀_•́)ง
    基于VS快速排序的单元测试
    POST GET
    Go对比其他语言新特性1(字符类型、类型转换、运算符、键盘输入、for、switch)
    四则运算问题
    软件工程第三次作业!
    Servlet
    结对编程1
    Kafka技术原理知识点总结
    KafkaStream简介
  • 原文地址:https://www.cnblogs.com/mowanying/p/11391213.html
Copyright © 2011-2022 走看看