ZOJ 2432 Greatest Common Increasing Subsequence(最长公共上升子序列+路径打印)

Greatest Common Increasing Subsequence

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1432

题目大意:给出两串数字,求他们的最长公共上升子序列(LCIS),并且打印出来。

Sample Input

1

5
1 4 2 5 -12
4
-12 1 2 4

Sample Output

2
1 4

分析:神奇就神奇在是LIS与LCS的组合

令dp[i][j]表示A串的前i个,与B串的前j个,并以B[j]为结尾的LCIS 的长度.

状态转移方程:

  f(A[i]==B[j])   dp[i][j]=max(dp[i-1][k])+1;  ( 1 <= k < j )

  else   dp[i][j]=dp[i-1][j];

然后选择循环顺序,就可以将算法的复杂度降为n*n.

代码如下:

 1 /*这个代码结果虽然对,跟样例的输出都不一样,而且两个输出数据之间有空行都没有实现,却能AC,有点匪夷所思*/
 2 # include<stdio.h>
 3 # include<string.h>
 4 #define MAX 550
 5 
 6 struct node{
 7     int x,y;
 8 }path[MAX][MAX];
 9 
10 int dp[MAX][MAX];
11 int s[MAX],t[MAX];
12 
13 int main(){
14     int T,i,j;
15     scanf("%d",&T);
16     while(T--)
17     {
18         memset(path,0,sizeof(path));
19         int n,m;
20         scanf("%d",&n);
21         for(i=1; i<=n; i++)
22             scanf("%d",&s[i]);
23         scanf("%d",&m);
24         for(i=1; i<=m; i++)
25             scanf("%d",&t[i]);
26         memset(dp,0,sizeof(dp));
27         int max = 0;
28         for(i=1; i<=n; i++)
29         {
30             max = 0;
31             int tx = 0,ty = 0;
32             for(j=1; j<=m; j++)
33             {
34                 dp[i][j] = dp[i-1][j];
35                 path[i][j].x = i-1;
36                 path[i][j].y = j;
37                 if( s[i] > t[j] && max < dp[i-1][j])
38                 {
39                     max = dp[i-1][j];
40                     tx = i-1;
41                     ty = j;
42                 }
43                 if( s[i] == t[j] )
44                 {
45                     dp[i][j] = max+1;
46                     path[i][j].x = tx;
47                     path[i][j].y = ty;
48                 }
49             }
50         }
51         max = -1;
52         int id;
53         for(i=1; i<=m; i++) 
54             if(dp[n][i]>max) 
55             {
56                 max = dp[n][i];
57                 id = i;
58             }
59             int save[MAX];
60             int cnt=0;
61             int tx,ty;
62             tx=n; ty=id;
63             while(dp[tx][ty] != 0 ) 
64             {
65                 int tmpx,tmpy;
66                 tmpx = path[tx][ty].x;
67                 tmpy = path[tx][ty].y;
68                 if(dp[tx][ty] != dp[tmpx][tmpy])
69                 {
70                     save[cnt++]=t[ty];
71                 }
72                 tx = tmpx; ty = tmpy;
73             }
74             printf("%d
",max);
75             for(i=cnt-1; i>=0; i--)
76                 printf("%d ",save[i]);
77             printf("
");
78     }
79     return 0;
80 }
原文地址:https://www.cnblogs.com/acm-bingzi/p/3263820.html