问题:
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
大意:
给你两个序列,求这两个序列的最长公共上升子序列的长度。
思路:
这就相当于是求最长公共序列和最长上升序列的合并。
状态迁移方程:dp[ i+1 ][ j+1 ]=max( dp[ i ][ j ]+1, dp[ i+1 ][ j ] ,dp[ i ][ j+1 ]),
代码:
#define N 510
#include<stdio.h>
#include<iostream>
#include<string>
#include<string.h>
#include<algorithm>
using namespace std;
int k[N],s[N];
int kl,sl;
int dp[N][N];//设dp[i+1][j+1]是第一个序列前i个与第二个序列前j个的最长公共上升子序列
long long int d[N][N];//保留每段以求出序列末尾的最小值
int main()
{
int c;scanf("%d",&c);
while(c--)
{
scanf("%d",&kl);
for(int i=0; i<kl; i++)
scanf("%d",&k[i]);
scanf("%d",&sl);
for(int i=0; i<sl ;i++)
scanf("%d",&s[i]);
memset(d,-0x3f,sizeof(d));
for(int i=0; i<kl; i++)
for(int j=0; j<sl; j++)
{
if(k[i]==s[j]&&d[i][j]<k[i])//序列可以延长
{
dp[i+1][j+1]=dp[i][j]+1;
d[i+1][j+1]=k[i];//保留最小值
}
else //不能延长
{
if(dp[i+1][j]>dp[i][j+1])//谁长留下谁
{
dp[i+1][j+1]=dp[i+1][j];
d[i+1][j+1]=d[i+1][j];
}
else if(dp[i+1][j]<dp[i][j+1])
{
dp[i+1][j+1]=dp[i][j+1];
d[i+1][j+1]=d[i][j+1];
}
else //一样长留下,序列末尾值最小的一个
{
dp[i+1][j+1]=dp[i+1][j];
d[i+1][j+1]=min(d[i+1][j],d[i][j+1]);
}
}
}
printf("%d\n",dp[kl][sl]);
if(c)printf("\n");
}
return 0;
}