ZOJ 2432 Greatest Common Increasing Subsequence

传送门

$Description$

求两个序列的最长上升序列

$Solution$

$f[i][j]$表示$a$序列匹配到$i$和$b$序列匹配到$j$的最长上升序列的长度,这里并不要求$a[i]==b[j]$。

两层循环,外层$i=1...n1$,内层$j=1...n2$

转移:

$f[i][j]=max(f[i-1][1...j-1](if b[j]<a[i]))+1$

这里的$max(f[i-1][1...j-1](ifb[j]<a[i]))$不用每次单独枚举,只要在循环内即使更新就可以了

$Code$

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #define Rg register
 5 #define il inline
 6 #define db double
 7 #define ll long long
 8 #define mem(a,b) memset(a,b,sizeof(a));
 9 #define go(i,a,b) for(Rg int i=a;i<=b;i++)
10 #define yes(i,a,b) for(Rg int i=a;i>=b;i--)
11 using namespace std;
12 il int read()
13 {
14     int x=0,y=1;char c=getchar();
15     while(c<'0'||c>'9'){if(c=='-')y=-1;c=getchar();}
16     while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+c-'0';c=getchar();}
17     return x*y;
18 }
19 const int N=501;
20 int T,n1,n2,ans,a[N],b[N],al[N],f[N][N],lst[N][N];
21 il void sol()
22 {
23     ans=0;mem(f,0);int x=n1,y=0,t;
24     go(i,1,n1)
25     {
26         t=0;
27         go(j,1,n2)
28         {
29             if(a[i]!=b[j])f[i][j]=f[i-1][j];
30             if(a[i]>b[j]&&f[i][j]>f[i][t])t=j;
31             if(a[i]==b[j])f[i][j]=f[i][t]+1,lst[i][j]=t;
32             //cout<<"f["<<i<<"]["<<j<<"]:"<<f[i][j]<<endl;
33         }
34     }
35     go(i,1,n2)if(f[n1][i]>ans)ans=f[n1][i],y=i;
36     t=0;
37     while(f[x][y])
38     {
39         while(a[x]!=b[y]){x--;if(!x)return;}
40         al[ans-t]=b[y],y=lst[x][y],t++;
41     }
42 }
43 int main()
44 {
45     T=read();
46     while(T--)
47     {
48         n1=read();go(i,1,n1)a[i]=read();
49         n2=read();go(i,1,n2)b[i]=read();
50         sol();
51         printf("%d\n",ans);
52         if(ans){go(i,1,ans)printf("%d ",al[i]);printf("\n");}
53     }
54     return 0;
55 }
View Code

猜你喜欢

转载自www.cnblogs.com/forward777/p/10885951.html
今日推荐