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\n",max); 75 for(i=cnt-1; i>=0; i--) 76 printf("%d ",save[i]); 77 printf("\n"); 78 } 79 return 0; 80 }
把每一件简单的事情做好,就是不简单;把每一件平凡的事情做好,就是不平凡!相信自己,创造奇迹~~