463D - Gargari and Permutations(思维+dp多个串的LCS)

https://codeforces.com/problemset/problem/463/D


思路:因为序列为排列,设dp[x]以x结尾能得到最长的LCS. 当x出现k次时,说明x能作为结尾,枚举能接在其前面的数即可 O(k*n^2)。

#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<cstdio>
#include<algorithm>
#define debug(a) cout<<#a<<"="<<a<<endl;
using namespace std;
const int maxn=1e3+100;
typedef long long LL;
inline LL read(){LL x=0,f=1;char ch=getchar();	while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
return x*f;}
LL a[6][maxn];
LL pos[6][maxn];
LL dp[maxn];
LL cnt[maxn];
vector<LL>v;
int main(void){
   ///cin.tie(0);std::ios::sync_with_stdio(false);
   LL n,k;cin>>n>>k;
   for(LL i=1;i<=k;i++){
        for(LL j=1;j<=n;j++){
            cin>>a[i][j];
            pos[i][a[i][j]]=j;
        }
   }
   for(LL i=1;i<=n;i++) dp[i]=1;
   LL ans=1;
   for(LL i=1;i<=n;i++){///枚举下标
       for(LL j=1;j<=k;j++){
          LL x=a[j][i];
          cnt[x]++;///当前这个数是否已经出现了k次
          if(cnt[x]<k) continue;
          ///考虑从前面的也已经出现了k次的集合中dp转移
          for(LL w=0;w<v.size();w++){
              LL num=v[w];
              bool flag=1;
              for(LL f=1;f<=k;f++){
                  if(pos[f][num]>pos[f][x]){
                    flag=0;break;
                  }
              }
              if(flag){
                 dp[x]=max(dp[x],dp[num]+1);
                 ans=max(ans,dp[x]);
              }
          }
          v.push_back(x);
       }
   }
   cout<<ans<<"\n";
   return 0;
}

猜你喜欢

转载自blog.csdn.net/zstuyyyyccccbbbb/article/details/115426462