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 }
View Code