Greatest Common Increasing Subsequenc
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
题意:求最长公共上升子序列。
做法:设f[i][j]表示以b[j]结尾的最长公共上升子序列长度。那么有f[i][j]=f[i-1][j],f[i][j]=max(f[i-1][k]){a[i]=b[j],a[i]>b[k]}
这样直接枚举需要三重,虽然对于本题似乎并不会超时(我不知道有几组数据。。)?但我们可以寻求更好的做法。
可以想到,在一重循环i中,a[i]>b[k]中的a[i]是固定的,也就是说,对于循环k,每次长度都只加1,实际上我们可以用一个 变量来维护当前
的j是否满足决策条件 val=max(val,f[i-1][j])(a[i]>b[j]),这样就直接降了一维复杂度。
PS:本题输出格式坑(每个输出间空两行)。
1 #include <cstdio> 2 #include <iostream> 3 #define N 607 4 #include <cstring> 5 using namespace std; 6 int n,m,T,ans; 7 int f[N][N],a[N],b[N]; 8 9 inline int max(int a,int b) {return a>b?a:b;} 10 11 void Init(){ 12 scanf("%d",&n); 13 for (int i=1;i<=n;i++) scanf("%d",&a[i]); 14 scanf("%d",&m); 15 for (int i=1;i<=m;i++) scanf("%d",&b[i]); 16 } 17 18 void Dp(){ 19 memset(f,0,sizeof(f)); 20 for (int i=1;i<=n;i++){ 21 int val=0; 22 if (b[0]<a[i]) val=f[i-1][0]; 23 for (int j=1;j<=m;j++){ 24 if (a[i]==b[j]) f[i][j]=val+1; 25 else f[i][j]=f[i-1][j]; 26 if (a[i]>b[j]) val=max(val,f[i-1][j]); 27 } 28 } 29 ans=0; 30 for (int i=0;i<=n;i++) ans=max(f[n][i],ans); 31 } 32 33 int main(){ 34 scanf("%d",&T); 35 for(;T--;){ 36 Init(); 37 Dp(); 38 printf("%d\n",ans); 39 if (T) printf("\n"); 40 } 41 }