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

AC通道

题目含义就是求最长公共上升子序列

首先考虑,最长公共上升子序列 = 最长上升子序列 + 最长公共子序列,可以通过LIS和LCS的思想去考虑本题目。

定义状态:

dp[i][j]表示A数组的前i个和B数组的前j个且以b[j]结尾的LCIS长度

考虑状态转移:

转移有两种情况

  1. a[ i ] == b[ j ]时候的转移,此时需要从 j 前面找一个比b[ j ]小的,已经构成LCIS的最大长度去更新dp[ i ][ j ],因此还需要去枚举 j 前面的所有的b[ j ],因此有
    if(b[k] < b[j])dp[i][j] = max(dp[i][j], dp[i - 1][k] + 1);

     

  2. a[ i ] != b[ j ]时,当前的最长的长度就是dp[ i - 1] [ j ],因为dp [ i ] [ j ]一定是以b[ j ]结尾的 

考虑完状态转移就写代码叭

#include <bits/stdc++.h>
using namespace std;
template <class T>
bool read(T & a){
	a = 0;
	int flag = 0;
	char ch;
	if((ch = getchar()) == '-'){
		flag = 1;
	}
	else if(ch >= '0' && ch <= '9'){
		a = ch - '0';
	}
	while ((ch = getchar()) >= '0' && ch <= '9'){
		a = a * 10 + ch - '0';
	}
	if(flag)a = -a;
	return true;
}
template <class T, class ... R>
bool read(T & a, R & ... b){
	if(!read(a))return 0;
	read(b...);
}
const int N = 3010;
int a[N], b[N], n, dp[N][N];
int main(){
//	freopen("LCIS_in.txt", "r", stdin);
	read(n);
	for (int i = 1; i <= n; i++)read(a[i]);
	for (int i = 1; i <= n; i++)read(b[i]);
	for (int i = 1; i <= n; i++){
		for (int j = 1; j <= n; j++){
			if(a[i] == b[j]){
				for (int k = 0; k < j; k++){
				/*
				 这个位置不从 k = 1开始的原因是
				 k = 0的情况就是前面没有构成的情况,不能省略 
				 */ 
					if(b[k] < b[j])dp[i][j] = max(dp[i][j], dp[i - 1][k] + 1);
				}
			}
			else dp[i][j] = dp[i - 1][j];
		}
	}
	int res = 0;
	for (int i = 1; i <= n; i++){
		res = max(res, dp[n][i]);
	}
	cout << res;
	return 0;
}

 

posted @ 2019-09-24 17:13  correct  阅读(164)  评论(0)    收藏  举报