Greatest Common Increasing Subsequence

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 7567    Accepted Submission(s): 2442


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
 
md终于来大招了:最长公共子序列
dp方程与LCS的类似,这是n^4做法:
dp[i][j]=
{
    max(dp[i-1][j],dp[i][j-1]);               //a[i]!=b[j]时
    max(dp[i-1][j-1],1,max(dp[di][dj])+1);     //a[i]==b[j]时,其中1<=di<i,1<=dj<j(且a[di]==b[dj]&&a[di]<a[i])
}
  第一种情况显然容易理解。
对于第二种情况:一是除去这个数前面的LCIS,二是这个数单独成一个LCIS(对于前面为0的情况此时显然更优),
三是这个LCIS是以这个数为结尾的,此时只需要前面的在满足LCIS结尾数<这个数的前提下的最长的LCIS,最后加1表示将这个数加入
 
 
 
 

#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
#define ql(a) memset(a,0,sizeof(a))
#define CIN(a) scanf("%d",&a)
#define COUT(a) printf("%d\n",a)
int dp[505][505];
int main()
{
int a[505],b[505];
int i,j,k=0,sumn,maxn,temp,tmp;
int n1,n2,t;
cin>>t;
while(t--){ql(dp);k++;
if(k>1) cout<<endl;
CIN(n1);
for(i=1;i<=n1;++i) CIN(a[i]);
CIN(n2);
for(i=1;i<=n2;++i) CIN(b[i]);
for(i=1;i<=n1;++i)
for(j=1;j<=n2;++j)
{
if(a[i]!=b[j]) dp[i][j]=max(dp[i][j-1],dp[i-1][j]);
else{maxn=0;
dp[i][j]=max(1,dp[i-1][j-1]);
for(int di=1;di<i;++di)
for(int dj=1;dj<j;++dj)
if(a[di]==b[dj]&&a[di]<a[i]) maxn=max(maxn,dp[di][dj]);
dp[i][j]=maxn+1;
}
}
COUT(dp[n1][n2]);
}
return 0;
}