CodeForce 113B 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 31 4 2 34 1 2 31 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;
}

原文地址:https://www.cnblogs.com/cautx/p/11599511.html

时间: 2024-10-11 09:49:31

CodeForce 113B DP的相关文章

codeforce 455A—— DP—— Boredom

Description Alex doesn't like boredom. That's why whenever he gets bored, he comes up with games. One long winter evening he came up with a game and decided to play it. Given a sequence a consisting of n integers. The player can make several steps. I

codeforce 597C-Subsequences(dp+树状数组)

题目和南阳那道题一样链接http://www.cnblogs.com/zzuli2sjy/p/4943774.html 代码: 1 #include<stdio.h> 2 #include<algorithm> 3 #include<string.h> 4 #include<stdlib.h> 5 #include<iostream> 6 #include<map> 7 typedef long long ll; 8 const ll

codeforce 382 div2 E —— 树状dp

题意:给一棵n个结点的无根树染色,求使每个结点距离为k的范围内至少有一个被染色的结点的总染色方法数目 分析:首先我们定义: 对于结点v, 如果存在一个黑色结点u距离v不超过k,则结点v被"控制" 首先将无根树转换成以1为根的有根树,设dp[v][i]为对于以v为根的子树,距离v最近的黑色结点深度为i时, 该子树中结点全部被控制或者可能在其他子树的影响下被全部控制的染色方法数. 下面来解释一下, 我们知道,当两个黑色结点距离不超过2*k+1时,其间的所有节点都被控制.那么当 i <

codeforce 417D Cunning Gena (状压DP)

原题地址:http://codeforces.com/problemset/problem/417/D 题意: Gena 为了解决m个问题,请他的朋友们帮忙,其中第i个朋友可以解决某mi个问题,需要花费xi卢布,并且要求安装至少ki个显示器,每个显示器需要b卢布. 问解决所有问题需要多少多少卢布 题解 考虑问题数目很小,可以状压DP. dp[S]表示当前状态的最优解,通过位运算进行转移. 考虑|没有逆运算,所以只能正推更新. 首先把朋友按照k排序,避免k的干扰. dp[][0]和dp[][1]分

codeforce 743D. Chloe and pleasant prizes 树dp

D. Chloe and pleasant prizes 题意:一颗以1为根的有根树,每个节点有点权,从中选出2个无相交的子树,使其权值和最大 思路:树dp裸题 dp[u][1] 记录以u为根 选一颗子树的最大值(包括u本身) dp[u][2]记录以u为根 选2颗树的最大值 dp[1][2] 即是答案 AC代码: #include "iostream" #include "string.h" #include "stack" #include &

【CodeForce】509F Progress Monitoring(树形情景区间DP)

题目大意:有一段深搜的代码,是遍历一个邻接矩阵,然后输出一个序列,这个邻接矩阵的原形是一棵树,那么现在就是要你根据序列,求出最多有多少个不同的树遍历之后可以得到相同的序列. 思路:这道题属于简单的区间DP,仔细点想就可以了. 第一种方法也是最直接的思路. 令dp[i][j]表示的是以i这个点为根,其余点为它的子树时,符合条件的最大个数. 从样例可以想到 1 2 3由于3和2交换之后,依然不会影响输出,所以假如1 2 xxx 3xxx,交换2,3节点下的树,也是不会影响序列的. 突破点就在此,dp

Codeforce 401D Roman and Numbers[数位DP+状态压缩]

给出数n和m,求n的所有排列中,模m得0的有多少个 n (1?≤?n?<?1018) and m (1?≤?m?≤?100). 暴力法我们直接枚举n的所有排列,显然18!超时. 考虑怎么dp 假设给了我们数n=23765 显然有 (237%m*10+6)%m=2376%m (367%m*10+2)%m=3672 我们很自然的想到了 这样的状态转移 dp[i][k] i代表取的数的状态 代表在取数状态为i的情况下模m为k的数有多少 比如 对于23765的356 取数状态为01011 dp方程就是

codeforce #505D - Recovering BST 区间DP

1025D 题意: 有一个递增序列,问能不能构建出一颗每条边的端点值都不互质的二叉排序树. 思路: 区间DP,但是和常见的区间DP不一样, 这里dp[i][j]表示的是区间[i,j]能否以i为根建立一个小二叉排序树. 所以可以得到dp[i][j] 为true, 要求在[i+1,j]中有一个k,dp[k][i+1]和dp[k][j]都为true. 或者在i点的左边取件中,即要求在[j][i-1]中有一个k,dp[k][j]和dp[k][i-1]都为true. #include <algorithm

CodeForce - 1187 E. Tree Painting (换根dp)

You are given a tree (an undirected connected acyclic graph) consisting of nn vertices. You are playing a game on this tree. Initially all vertices are white. On the first turn of the game you choose one vertex and paint it black. Then on each turn y