HDU1423 最长公共上升子序列LCIS

Problem Description
This is a problem from ZOJ 2432.To make it easyer,you just need output the length of the subsequence.
 
Input
Each sequence is described with M - its length (1 <= M <= 500) and M integer numbers Ai (-2^31 <= Ai < 2^31) - the sequence itself.
 
Output
output print L - the length of the greatest common increasing subsequence of both sequences.
 
Sample Input
1 5 1 4 2 5 -12 4 -12 1 2 4
 
Sample Output
2
 
Source
 
Recommend
lcy
分析:经典的LCIS问题,用dp求解,既然问题是LIS+LCS,那么状态转移方程肯定是结合了这两道题的。观察一下这两道题的方程有啥特点LIS中的状态是以某一位结尾的,LCS中的表示到第几位,那么LCIS就要把这两个特点结合起来,一维表示到第几位,一维表示以某一位结尾,那么设f[i][j]表示a中前i个和b中前j个的LCIS,并且以b[j]结尾,显然如果a[i] != b[j],那么f[i][j] = f[i-1][j],否则f[i][j] = max{f[i-1][k]} (1 <= k < j && b[k] < b[j]),三重循环,复杂度要爆表了.
      考虑一下能不能只用两重循环,找最大值的部分,我们要找到b[k] < b[j]的最大值f[i-1][k],我们能不能不枚举k呢?注意到我们每次枚举j的时候都是重复找了最大值的,如果a[i] > b[k]了,就更新最大值,因为我们要用最大值来更新a[i] = b[k]的情况,既然a[i]都大于b[k]了,那么自然b[k] < b[k'],因为都是顺序枚举的,保证都会更新到.
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int inf = 0x7ffffff;

int t,l1,l2,a[510],b[510],f[510][510],ans,maxx;

int main()
{
    scanf("%d",&t);
    while (t--)
    {
    memset(f,0,sizeof(f));
    ans = 0;
       scanf("%d",&l1);
       for (int i = 1; i <= l1; i++)
       scanf("%d",&a[i]);
       scanf("%d",&l2);
       for (int i = 1; i <= l2; i++)
       scanf("%d",&b[i]);
    for (int i = 1; i <= l1; i++)
    {
    maxx = 0;
    for (int j = 1; j <= l2; j++)
    {
        f[i][j] = f[i - 1][j];
        if (a[i] > b[j])
        maxx = max(maxx,f[i-1][j]);
        if (a[i] == b[j])
        f[i][j] = maxx + 1;
    }
    }
    for (int i = 1; i <= l2; i++)
    ans = max(ans,f[l1][i]);
    if (t != 0)
    printf("%d

",ans);
    else
    printf("%d
",ans);
    }

    return 0;
}
原文地址:https://www.cnblogs.com/zbtrs/p/7478417.html