Codeforces 463D Gargari and Permutations【思维建图+Floyd跑最长路】不愧是CF的评测姬

D. Gargari and Permutations
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

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].


题目大意:


给你K个长度为N的序列(全排列),让你求这K个序列的最长公共子序列。


思路:


1、如果有两个值vala,valb.其在第一个序列的位子满足posa<posb,并且在第二个第三个第四个........序列的位子同时满足posa<posb.那么对应两个位子就可以建立一条边,posa->posb.表示有一个子序列长度为2,并且肯定这个子序列是作为公共部分出现的。


2、那么建好图之后,问题就转化到求最长路上边来了。

因为点并不多,而且给了2s.

另外评测机是CF.

所以为了省事,写了Floyd跑的最长路。

那么ans=max(map【i】【j】);

看到更多用Dp来搞的,自己想到这么做还是稍有成就感的哈~~~


Ac代码:

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<vector>
using namespace std;
int map[1005][1005];
vector<int >mp[1005];
int a[6][1005];
int pos[6][1005];
int b[1005];
int dp[1005];
int main()
{
    int n,k;
    while(~scanf("%d%d",&n,&k))
    {
        memset(map,0,sizeof(map));
        for(int i=0;i<k;i++)
        {
            for(int j=0;j<n;j++)
            {
                scanf("%d",&a[i][j]);
                pos[i][a[i][j]]=j;
            }
        }
        for(int i=0;i<n;i++)
        {
            for(int j=i+1;j<n;j++)
            {
                int fst=a[0][i];
                int sec=a[0][j];
                int flag=0;
                for(int z=1;z<k;z++)
                {
                    if(pos[z][fst]<pos[z][sec])continue;
                    else flag=1;
                }
                if(flag==0)
                {
                    map[i][j]=1;
                }
            }
        }
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<n;j++)
            {
                for(int k=0;k<n;k++)
                {
                    if(map[j][i]==0||map[i][k]==0)continue;
                    map[j][k]=max(map[j][k],map[j][i]+map[i][k]);
                }
            }
        }
        int output=0;
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<n;j++)
            {
                output=max(output,map[i][j]);
            }
        }
        printf("%d\n",output+1);
    }
}





  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值