CodeForces 463D DP

Gargari got bored to play with the bishops and now, after solving the problem about them, he is trying to do math homework. In a math book he have found k permutations. Each of them consists of numbers 1, 2, ..., n in some order. Now he should find the length of the longest common subsequence of these permutations. Can you help Gargari?

You can read about longest common subsequence there: https://en.wikipedia.org/wiki/Longest_common_subsequence_problem


Input

The first line contains two integers n and k (1 ≤ n ≤ 1000; 2 ≤ k ≤ 5). Each of the next k lines contains integers 1, 2, ..., n in some order — description of the current permutation.

Output

Print the length of the longest common subsequence.

Examples
Input
4 3
1 4 2 3
4 1 2 3
1 2 4 3
Output
3
Note

The answer for the first test sample is subsequence [1, 2, 3].

 

OJ-ID:
CodeForce 113B

author:
Caution_X

date of submission:
2019-09-27

tags:
DP

description modelling:
求多个数列的LCS

major steps to solve it:
1.dp[i]:表示以数字i结尾得到的LCS,pos[i][j]表示数字j再第i个数列的位置,cnt[i]表示数字i出现了几次
2.从每个数列第一个数开始往后遍历,当cnt[i]=k时说明i可以作为LCS的一部分了
3.接下来需要讨论一下,在LCS中加入i对答案的影响
4.我们用vector<>存入所有可以作为LCS一部分的值,然后遍历vector中的数,判断二者的pos,来决定i应该插入在哪一个位置
5.遍历完成后vector<>加入i并且重新从2步骤开始

warnings:

AC code:

#include<bits/stdc++.h>
using namespace std;
int a[6][1010];
int dp[1010];//以i结尾的LCS
int cnt[1010],pos[6][1010];//pos[i][j]=:j在 i中出现的位置
vector<int> q;
int main()
{
    //freopen("input.txt","r",stdin);
    int n,k,ans=0;
    scanf("%d%d",&n,&k);
    for(int i=0;i<k;i++)
        for(int j=0;j<n;j++)
            scanf("%d",&a[i][j]);
    memset(cnt,0,sizeof(cnt));
    memset(dp,0,sizeof(dp));
    for(int i=0;i<n;i++){
        for(int j=0;j<k;j++){
            int cur=a[j][i];
            pos[j][cur]=i;
            cnt[cur]++;
            if(cnt[cur]==k){
                if(q.empty())    dp[cur]=1;
                else{
                    for(int kk=0;kk<q.size();kk++){
                        bool flag=false;
                        for(int l=0;l<k;l++){
                            if(pos[l][q[kk]]>pos[l][cur]){
                                flag=true;
                                break;
                            }
                        }
                        if(!flag)    dp[cur]=max(dp[cur],dp[q[kk]]+1);
                        else    dp[cur]=max(dp[cur],1);
                    }
                }
                ans=max(ans,dp[cur]);
                q.push_back(cur);
            }
        }
    }
    printf("%d\n",ans);
    return 0;
}
View Code

 




posted on 2019-09-27 17:58  Caution_X  阅读(137)  评论(0编辑  收藏  举报

导航