zoukankan      html  css  js  c++  java
  • 最长上升子序列的回溯 ZOJ 2432

    题目大意:

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

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

    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
    " , maxn);
    69         for(int i = cnt - 1 ; i>=0 ; i--)
    70             printf("%d " , a[rec[i]]);
    71         printf("
    ");
    72         if(T>0) puts("");
    73     }
    74     return 0;
    75 }
  • 相关阅读:
    十大开源CRM
    EL表达式【转】
    zk调用js(转)
    MVC4学习笔记(三) 数据验证设计
    MVC4学习笔记(一) 认识MVC
    MVC4学习笔记(四) MVC界面设计
    hibernate介绍
    如何在oracle中导入dmp数据库文件
    JS的delete操作
    使用JavaScript给Html元素加边框
  • 原文地址:https://www.cnblogs.com/CSU3901130321/p/4182811.html
Copyright © 2011-2022 走看看