This is a problem from ZOJ 2432.To make it easyer,you just need output the length of the subsequence.
InputEach sequence is described with M - its length (1 <= M <= 500) and M integer numbers Ai (-2^31 <= Ai < 2^31) - the sequence itself.Outputoutput 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 4Sample Output
2
题意:是求最长公共上升子序列
最长公共上上升子序列的详解:http://www.cnblogs.com/wd-one/p/4470844.html
思路:用动态规划:
dp[i][j]存的是当a数组长度为i时,b数组长度为j时且b[j]为结尾的最长公共上升子序列;
代码里有思路和解释:
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int dp[550][550];//dp[i][j] 存的是当a数组长度为i时,b数组长度为j时且b[j]为结尾的
int n,m; //最长公共上升子序列;
int a[550],b[550];
// 当a[i]!=b[j] 时,dp[i][j]=dp[i-1][j];
//因为 d[i][j] 是以 b[j] 为结尾的LCIS,
//如果 d[i][j] > 0 那么就说明 a[1] .... a[i] 中必然有一个元素 a[k] 等于 b[j]
// 当a[i]==b[j] 时,d[i][j]=max(dp[i-1][k])+1;其中b[j]>b[k];
只有当a[i] > b[j]时,才更新Max, 保证了所求序列是上升的。
int main()
{
int i,j,k,t;
scanf("%d",&t);
while(t--)
{
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]);
int Max,M=0;
memset(dp,0,sizeof(dp));
for(i=1;i<=n;i++)
{
Max=0;
for(j=1;j<=m;j++)
{
if(a[i]!=b[j])
{
dp[i][j]=dp[i-1][j];
if(a[i]>b[j]&&dp[i-1][j]>Max)
{
Max=dp[i-1][j];
}
}
//要理解为啥a[i]>b[j]时;
// a[i] 是外层循环,当和内层循环b[j]相等时,这一步是为了在找出前面
// 小于b[j] 的最大值 ,就是为啥是dp[i-1][j]>Max而不是dp[i][j],因为要找以b[j]结尾的最长公共上升子序列,当
//b[j]==a[i] ,也就是找a[i]的,若写dp[i][j]的话,就把a[i]也算进去了,a[i] 只能结尾于最长公共子序列的末尾;
else
{
dp[i][j]=Max+1;
}
M=max(M,dp[i][j]);
}
}
printf("%d\n",M);
if(t) printf("\n");
}
return 0;
}