cf463d

这题说的是给了k个串算出这k个串的最长公共子序列,这k个串每个串都是由1--n的数字组成的。

将第一串的数字按照顺序重新编号为123...n 然后后面的串按照这个编号重新标号,就转化为下面每个串大最长递增子序列的问题,然后我们对于每个串计算出后面比他大的数然后建一条边(用邻接矩阵存)然后可以判断出从a到b点是否有k-1条这样我们专门挑那些k-1条的走这样保证每个序列中都有这样最后dfs算出最长的那个

#include <iostream>
#include <cstdio>
#include <string.h>
using namespace std;
const int MAX_N = 1009;
int renum[MAX_N];
int edg[MAX_N][MAX_N],dp[MAX_N];
int rt[6][MAX_N],ans,R,n;
bool use[MAX_N];
void dfs(int loc, int len){
       ans=max(len,ans);
       dp[loc]=len;
       for(int i=loc+1; i<=n; ++i)
       if(edg[loc][i]==R&&dp[i]<len+1){
         dfs(i,len+1);
       }
}
int main()
{
     int k;
     while(scanf("%d%d",&n,&k)==2){
          for(int i =1; i<=n; ++i){
              scanf("%d",&rt[0][i]);
              renum[rt[0][i]]=i;
          }
          R=k-1;
          for(int i=1; i<k; ++i){
                rt[i][0]=0;
               for(int j=1; j<=n; ++j){
                scanf("%d",&rt[i][j]);
                 rt[i][j]=renum[rt[i][j]];
               }
          }
          memset(edg,0,sizeof(edg));
          for(int i=1; i<k; i++){
               for(int j =0; j<=n; ++j){
                 for(int t=j+1; t<=n; ++t)
                  if(rt[i][j]<rt[i][t]) edg[rt[i][j]][rt[i][t]]++;
               }
          }
          ans=0;
          memset(dp,0,sizeof(dp));
          dfs(0,0);
          printf("%d
",ans);
     }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/Opaser/p/3964390.html