• 最长公共上升子序列


    输入格式

    第一行包含一个整数N,表示数列A,B的长度。
    第二行包含N个整数,表示数列A。
    第三行包含N个整数,表示数列B。

    输出格式

    输出一个整数,表示最长公共上升子序列的长度。

    数据范围

    1≤N≤3000,序列中的数字均不超过231−1

    思路:

    状态表示:f[i][j]表示A数组中的前i个元素以及B数组的前j个元素,且以B[j]结尾的最长公共上升子序列
    状态计算:分情况讨论,当A[i]不包含在LICS中时,那么f[i][j] == f[i-1][j]
    当A[i]包含在LICS中时,由于B[j]是结尾元素,那么一定有A[i]==B[j],然后遍历1~j的所有元素k,当B[j] > B[k]时,f[i][j] == max(f[i][j], f[i-1][k] + 1)

    Code: O(n3)

    #include <bits/stdc++.h>
    
    using namespace std;
    
    const int N = 3010;
    
    int n;
    int a[N],b[N];
    int f[N][N];
    
    int main()
    {
        cin >> n;
        for(int i = 1;i <= n;i++) cin >> a[i];
        for(int i = 1;i <= n;i++) cin >> b[i];
        
        for(int i = 1;i <= n;i++)
        {
            for(int j = 1;j <= n;j++)
            {
                f[i][j] = f[i-1][j];
                if(a[i] == b[j])
                {
                    f[i][j] = max(f[i][j], 1);
                    for(int k = 1;k < j;k++)
                        if(b[k] < b[j])
                            f[i][j] = max(f[i][j], f[i-1][k] + 1);
                }
            }
        }
        int ans = 0;
        for(int i = 1;i <= n;i++) ans = max(ans, f[n][i]);
        
        cout << ans << endl;
        return 0;
    } 
    

    这个时间复杂度在3000的数据范围内很容易TLE,我们可以想办法优化一下,优化方法就是把比较的地方的b[j]换成a[i]

    for(int i = 1;i <= n;i++)
        {
            for(int j = 1;j <= n;j++)
            {
                f[i][j] = f[i-1][j];
                if(a[i] == b[j])
                {
                    f[i][j] = max(f[i][j], 1);
                    for(int k = 1;k < j;k++)
                        if(b[k] < a[i])
                            f[i][j] = max(f[i][j], f[i-1][k] + 1);
                }
            }
        }
    

    当换成a[i]后我们可以发现,最内层的循环与j没有什么关系,而这层循环求的就是f[i][k]的最大值 (1 <= k < j,且b[k] < a[i] (b[j])),那么我们可以用一个变量表示最大值

    for(int i = 1;i <= n;i++)
        {
            int maxv = 0;
            for(int j = 1;j <= n;j++)
            {
                f[i][j] = f[i-1][j];
                if(a[i] == b[j]) f[i][j] = max(f[i][j], maxv + 1);
                if(b[j] < a[i]) maxv = max(maxv,f[i][j]);
            }
        }
    

    最后又发现在整个DP过程中,第一维是没有用的,可以优化掉,那么就得到了最终代码

    #include <bits/stdc++.h>
    
    using namespace std;
    
    const int N = 3010;
    
    int a[N],b[N];
    int f[N];
    
    int main()
    {
        int n;
        cin >> n;
        for(int i = 1;i <= n;i++) cin >> a[i];
        for(int i = 1;i <= n;i++) cin >> b[i];
        
        for(int i = 1;i <= n;i++)
        {
            int maxv = 0;
            for(int j = 1;j <= n;j++)
            {
                if(a[i] == b[j]) f[j] = max(f[j], maxv + 1);
                if(b[j] < a[i]) maxv = max(maxv,f[j]);
            }
        }
        
        int ans = 0;
        for(int i = 1;i <= n;i++) ans = max(ans, f[i]);
        cout << ans << endl;
        
        return 0;
    }
    
  • 相关阅读:
    VS2017常用快捷键
    浅谈JS之setTimeout与setInterval
    你真的了解foreach吗?
    IEnumerable和IEnumerator详解
    Cesium坐标系及坐标转换详解
    NPM常用指令
    ASP.NET Web API 2系列(三):查看WebAPI接口的详细说明及测试接口
    【nginx】安装nginx
    【redis】本地连接服务器的redis教程
    Mysql5.7及以上版本 ONLY_FULL_GROUP_BY报错的解决方法
  • 原文地址:https://www.cnblogs.com/zcxy/p/13059027.html
Copyright © 2020-2023  润新知