Codeforces Round #264 (Div. 2) D. Gargari and Permutations 多序列LIS+dp好题

http://codeforces.com/contest/463/problem/D

求k个序列的最长公共子序列。

k<=5


肯定 不能直接LCS

网上题解全是图论解法...我就来个dp的解法吧

首先,让我们创建的位置阵列的每个序列pos[k][N]。在这个数组,我们存储这n个数字(从1到n)在这k个序列中各个位置,然后按数大小排序。 

DP [I]标记的最大长度共同序列,我们可以通过使用第一个序列的第i个元素生成。为此,我们遍历所有可能以前的编号(J),看看我们是否能延长DP [J]到DP [I]。

对于给定的J<I,只有在所有的序列中J的位置前与I,才能更新DP[I] = max(DP[J] + 1).

#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <string>
#include <queue>
#include <vector>
#include<set>
#include <iostream>
#include <algorithm>
using namespace std;
#define RD(x) scanf("%d",&x)
#define RD2(x,y) scanf("%d%d",&x,&y)
#define clr0(x) memset(x,0,sizeof(x))
typedef long long LL;
vector <int> pos[1005];
int dp[1005];
int main()
{
    int n,k,x;
    RD2(n,k);
    for(int i = 0;i < k;++i){
        for(int j = 1;j <= n;++j){
            RD(x);
            pos[x].push_back(j);
        }
    }
    sort(pos+1,pos+n+1);
    int ans = 1;
    for(int i = 1;i <= n;++i)
        dp[i] = 1;
    for(int i = 2;i <= n;++i){
        for(int j = 1;j < i;++j){
            bool ok = true;
            for(int l = 0;l < k;++l){
                if(pos[j][l] > pos[i][l]){
                    ok = false;
                    break;
                }
            }
            if(ok){
                dp[i] = max(dp[j]+1,dp[i]);
            }
        }
        ans = max(ans,dp[i]);
    }
    printf("%d
",ans);
    return 0;
}


原文地址:https://www.cnblogs.com/zibaohun/p/4050741.html