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

    题目链接:https://www.acwing.com/problem/content/274/

    经典题,首先我们知道最长上升子序列和最长公共子序列的求法,
    那么最长上升公共子序列就是把两者的状态结合一下:(dp[i][j]) 表示 (A) 的前 (i) 个字符和 (B) 的前 (j) 个字符构成的以 (B[j]) 结尾的 (LCIS)

    转移方程即为:

    [dp[i][j] = egin{cases} dp[i][j] = dp[i-1][j]&A[i] eq B[j] \ max_{0leq k<j,B[k]<B[j]}{dp[i-1][j] + 1} & A[i] = B[j]\ end{cases} ]

    这样直接转移的复杂度是 (O(n^3))

    而我们发现,当 (A[i] = B[j]) 时,(B[k] < B[j]) 的条件可以改写成 (B[k] < A[i]), 我们发现转移时,决策集合不会减少, 所以如果记录一下 (i - 1) 这一层,(dp[i-1][j]) 的前缀满足条件的最大值,就可以做到 (O(1)) 转移,时间复杂度就降为 (O(n^2))

    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    typedef long long ll;
    
    const int maxn = 3010;
    
    int n;
    int a[maxn], b[maxn];
    int f[maxn][maxn];
    
    ll read(){ ll s = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar(); } while(ch >= '0' && ch <= '9'){ s = s * 10 + ch - '0'; ch = getchar(); } return s * f; }
    
    int main(){
    	n = read();
    	for(int i = 1 ; i <= n ; ++i) a[i] = read();
    	for(int i = 1 ; i <= n ; ++i) b[i] = read();
    	
    	for(int i = 0 ; i <= n ; ++i) f[i][0] = 0;
    	
    	int mx = 0;
    	for(int i = 1 ; i <= n ; ++i){
    		mx = 0;
    		for(int j = 1 ; j <= n ; ++j){
    			if(a[i] == b[j]){
    				f[i][j] = mx + 1;
    			} else{
    				f[i][j] = f[i - 1][j];
    			}
    			if(b[j] < a[i]) mx = max(mx, f[i - 1][j]);
    		}
    	}
    	
    	int ans = 0;
    	for(int i = 1 ; i <= n ; ++i){
    		ans = max(ans, f[n][i]);
    	}
    	
    	printf("%d
    ", ans);
    	
    	return 0;
    }
    
  • 相关阅读:
    SQL第3课:具有约束的查询(第2部分)
    SQL第1课:SELECT查询
    idea快捷键
    Vue基础
    分布式基础
    数据结构-线性表
    常用算法
    数据结构-概述
    Django使用Jinja2模板引擎
    宿主机nginx使用容器php-fpm处理php请求
  • 原文地址:https://www.cnblogs.com/tuchen/p/14099602.html
Copyright © 2011-2022 走看看