题目大意:

找一组最长上升公共子序列,并把任意一组满足的情况输出出来

 

最长公共上升子序列不清楚可以先看这篇文章

http://www.cnblogs.com/CSU3901130321/p/4182618.html

 

然后在这基础上加回溯,我自己一开始利用两个一维数组写回溯,测了很多数据都没问题

但一直给segment fault,网上也看到有人跟我一样说不知道为什么,一维数组的代码主要函数先放在这里留待以后看能否解决,或者有大神帮忙解决

 1 int dp[N] , a[N] , b[N] , rec[N] , fa[N] , src[N] , maxn , cnt;
 2 
 3 void LCIS(int m , int n)
 4 {
 5     memset(dp , 0 , sizeof(dp));
 6     memset(src , 0 , sizeof(src));
 7     memset(fa , 0 , sizeof(fa));
 8     for(int i = 1 ; i<=m ; i++){
 9         int  k = 0;
10         for(int j = 1 ; j<=n ; j++){
11             if(a[i] == b[j]){
12                 if(dp[j] < dp[k] + 1){
13                     dp[j] = dp[k] + 1;
14                     src[j] = i;
15                     fa[i] = src[k];
16                 }
17             }
18             if(a[i] > b[j] && dp[k] < dp[j]) k = j;
19         }
20     }
21 
22     maxn = 0 , cnt = 0;
23     int s;
24     for(int i = 1 ; i <= n ; i++)
25     {
26         if(maxn < dp[i])
27             maxn = dp[i] , s = src[i];
28     }
29     rec[cnt++] = s;
30     while(fa[s]){
31         rec[cnt++] = fa[s];
32         s = fa[s];
33     }
34 }
View Code


后来自己改成了二维数组来回溯

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 using namespace std;
 5 const int N = 1005;
 6 #define max(a,b) a>b?a:b
 7 int dp[N] , a[N] , b[N] , rec[N] , maxn , cnt;
 8 int s[N][N]; //用来回溯,记录前一次出现最大的j的位置,因为那个位置一定是会出现b[pos] = 某个a[i]的
 9 
10 void TraceBack(int i , int j)
11 {
12     if(i < 1 || j < 1) return ;
13    // cout<<"here: "<<i<<" "<<s[i][j]<<endl;
14     if(s[i][j] >= 0){
15         rec[cnt++] = i;
16 
17         TraceBack(i-1 , s[i][j]);
18     }else TraceBack(i-1 , j);
19 }
20 
21 void LCIS(int m , int n)
22 {
23     memset(dp , 0 , sizeof(dp));
24     memset(s , -1 , sizeof(s));
25     for(int i = 1 ; i<=m ; i++){
26         int  k = 0;
27         for(int j = 1 ; j<=n ; j++){
28             if(a[i] == b[j]){
29                 if(dp[j] < dp[k] + 1){
30                     dp[j] = dp[k] + 1;
31                     s[i][j] = k;//记录上一次出现在最长子序列中能够进行匹配的j的位置
32                 }
33             }
34             if(a[i] > b[j] && dp[k] < dp[j]) k = j;
35         }
36     }
37 
38     maxn = 0 , cnt = 0;
39     int pos ;
40     //我自己写的函数原因,所以必须找到第一个出现最大值的位置pos,保证在这个位置会出现某个a[i]与其匹配
41     /*这里从后往前找和从前往后找效果一样,但是输出的序列可能不同,
42     但是题目要求只输出一种情况所以也没问题,方向找,输出的正好是样例的结果
43     for(int i = 1 ; i<=n ; i++) 也确实AC了没问题
44     */
45     for(int i = n ; i >= 1 ; i--)
46     {
47         if(maxn < dp[i])
48             maxn = dp[i] , pos = i;
49     }
50     TraceBack(m , pos);
51 }
52 
53 int main()
54 {
55     int m , n , T;
56     scanf("%d" , &T);
57     while(T--){
58         scanf("%d" , &m);
59         for(int i = 1 ; i<=m ; i++)
60             scanf("%d" , a+i);
61 
62         scanf("%d" , &n);
63         for(int i= 1 ; i<=n ; i++)
64             scanf("%d" , b+i);
65 
66         LCIS(m , n);
67 
68         printf("%d\n" , maxn);
69         for(int i = cnt - 1 ; i>=0 ; i--)
70             printf("%d " , a[rec[i]]);
71         printf("\n");
72         if(T>0) puts("");
73     }
74     return 0;
75 }

 

 posted on 2014-12-24 16:57  Love风吟  阅读(283)  评论(0编辑  收藏  举报