LCIS (最长公共上升子序列)
题目含义就是求最长公共上升子序列
首先考虑,最长公共上升子序列 = 最长上升子序列 + 最长公共子序列,可以通过LIS和LCS的思想去考虑本题目。
定义状态:
dp[i][j]表示A数组的前i个和B数组的前j个且以b[j]结尾的LCIS长度
考虑状态转移:
转移有两种情况
- 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); -
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;
}
本文来自博客园,作者:correct,转载请注明原文链接:https://www.cnblogs.com/correct/p/12862029.html

浙公网安备 33010602011771号