【hdu1423】【DP】最长公共上升子序列

Greatest Common Increasing Subsequence

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

题目大意:hdu1423

输入多组数据,每组数据都有两个数字串,每个数字串输入长度M和串A,要求输出两个串的最长公共子序列的长度。(注意:每两组输出间都有空行)


-----------------------------------------------------------------------------------------------------------------------------------------------------


计算最长上升子序列时,我们设 f[i] 表示以 A[i] 为结尾的最长上升子序列长度。对于每一个 i ,每次查询一个 j ,满足 A[j] 有状态转移方程式 f[i]=max(f[i],f[j]+1)|1<=j

计算最长公共子序列时,我们设f[i][j]为 A 数组下表到 i ,B 数组下表到 j 时所产生的最长公共子序列的长度。
即有状态转移方程式 


f[i][j]=f[i-1][j-1]+1     |A[i]==B[j]
 max(f[i-1][j],f[i][j-1]) |A[i]!=B[j]


现在题目要求最长公共上升子序列,于是我们设 f[i][j] 表示A以 i 结尾,B 以 j 结尾的时候,与A序列构成最长公共上升子序列的长度。
如果某一个时刻 A[i]==B[j],那么显然,我们就应该在 f[i-1][0] 到 f[i-1][j-1] 中,找一个最大的 f 值来更新 f[i][j] ,此处类似最长上升子序列的思想。
若 A[i]!=B[j] ,则 f[i][j]= f[i-1][j],此处类似最长公共子序列。
于是有状态转移方程式:


f[i][j]=f[i-1][j]       |A[i]!=B[j]
  max(f[i-1][k]+1)      |A[i]==B[j] 0<=k

时间复杂度为 len(A)*len(B)^2
对于本题 M<=500 的数据已经够了。


那么还可以优化吗?
我们不妨记录一下 f[i-1][k] 最大值,因为当 A[i]==B[j] 时我们需要查找最大值,B[k] 时间复杂度便降到了 len(A)*len(B)。
当然空间也可以用滚动数组优化。
状态转移方程式可化为:


 f [ j ] =f[j]         |A[i]!=B[j]
          max_f+1      |A[i]==B[j]   
 max_f=max(max_f,f[j]) |0<=k

下附AC代码:

#include
#include
#include
using namespace std;

#define MAXN 5000
#define MAXM 10000
#define INF 0x3f3f3f3f
typedef long long LL;

int A[MAXN+10],B[MAXN+10];
int f[MAXN+10];
int N,M;
int main()
{
    int Case;
    scanf("%d",&Case);
    
    while(Case--)
    {
        int i,j;
        scanf("%d",&N);
        for(i=1;i<=N;++i)
            scanf("%d",&A[i]);
        scanf("%d",&M);
        for(i=1;i<=M;++i)
            scanf("%d",&B[i]);
        
        memset(f,0,sizeof(f));
        int ans=0;
        for(i=1;i<=N;++i)
        {
            int max_f=0;
            for(j=1;j<=M;++j)
            {
                if(A[i]==B[j])
                    f[j]=max(f[j],max_f+1);
                
                if(A[i]>B[j]&&max_f


吐槽:之前将更新max时的“A[i]>B[j]”写成了“A[i]>=B[j]”,在HDU上都过了,可见数据之水。

你可能感兴趣的:(动态规划)