Codeforces 463D. Gargari and Permutations【DP】

题目大意:

给出1~n的k个排列(2<=k<=5),要求其中的最长公共子序列。

做法:

算是不难的DP,dp[i]表示以i为结尾的最长公共子序列的长度,由于每个数在一个排列中只可能出现一次,我们用一个二维数组pos[i][j]表示数字j在第i行出现在第几个位置,再用一个数组cnt[i] 记录i出现了多少次;当第i个数出现了k次之后,说明能够以该数为结尾构成公共子序列,那么dp[i]=max(dp[j]+1),其中i,j满足pos[u][i]>pos[u][j](1<=u<=k);当然,为了节约时间,我们可以把之前已经计算过的dp[i]值的下标存到vector里面,这样只需要遍历这个vector找出符合条件的数即可.

代码:

#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#define N 1010
using namespace std;
int pos[6][N],cnt[N],a[6][N],dp[N];
vector<int> q;
int main()
{
    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]);
    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.size()==0) 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][cur]<pos[l][q[kk]]) {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(a[j][i]);
            }
        }
    cout<<ans<<endl;
    return 0;
}
时间: 2024-08-25 01:19:47

Codeforces 463D. Gargari and Permutations【DP】的相关文章

codeforces 463D Gargari and Permutations(dp)

题目 参考网上的代码的... //要找到所有序列中的最长的公共子序列, //定义状态dp[i]为在第一个序列中前i个数字中的最长公共子序列的长度, //状态转移方程为dp[i]=max(dp[i],dp[j]+1); j<i //先预处理出两个数在所有序列中的位置关系, //例如两个数a和b,只要在任意一个序列中a在b的后面,则记after[a][b]=1. //在递推的时候如果!after[a][b],则进行状态转移. #include <cstdio> #include <cs

Codeforces 463D Gargari and Permutations(求k个序列的LCS)

题目链接:http://codeforces.com/problemset/problem/463/D 题目大意:给你k个序列(2=<k<=5),每个序列的长度为n(1<=n<=1000),每个序列中的数字分别为1~n,求着k个序列的最长公共子序列是多长?解题思路:由于每个序列的数字分别为1~n即各不相同,所以可以用pos[i][j]记录第i个序列中j的位置.设dp[i]表示以i结尾的最长公共子序列长度,那么我们可以按顺序遍历第一个序列的位置i,再在第一个序列中枚举位置j(j<

Codeforces 999F Cards and Joy 【dp】【性质】

1 #include<iostream> 2 #include<map> 3 #include<cstring> 4 using namespace std; 5 6 7 //只需要考虑每个number带来的贡献,不是任何人favorite number的数没有贡献 8 int a[5005],h[15],favorite[505];//favorite[i]为第i个player的favorite number 9 int vis[100005],ans; 10 map

hdoj 2391 Filthy Rich 【DP】

题目大意:有个二维数组,你从(0,0)出发,最终到(n,m), 在这个二维数组中,每个位置dp[i][j]都有一定量的黄金,你可以拾取,问你最多能失去多少,并且,你的方向有下,右, 斜向下三个方向: 策略:就是每一个都加上它的上方向与左方向的最大值,这样到最后就是最大值.详情见代码 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2391 代码: #include<stdio.h> #include<string.h> int dp[1

HDOJ1176 免费馅饼 【DP】+【经典数塔】

免费馅饼 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 23986    Accepted Submission(s): 8093 Problem Description 都说天上不会掉馅饼,但有一天gameboy正走在回家的小径上,忽然天上掉下大把大把的馅饼.说来gameboy的人品实在是太好了,这馅饼别处都不掉,就掉落在他身旁的1

nyoj 325 zb的生日 【DP】||【DFS】

两种方法: 第一种:将总数一半当做背包,用总数-2*最多能装的数目就是所求: 第二种:深搜: zb的生日 时间限制:3000 ms  |  内存限制:65535 KB 难度:2 描述 今天是阴历七月初五,acm队员zb的生日.zb正在和C小加.never在武汉集训.他想给这两位兄弟买点什么庆祝生日,经过调查,zb发现C小加和never都很喜欢吃西瓜,而且一吃就是一堆的那种,zb立刻下定决心买了一堆西瓜.当他准备把西瓜送给C小加和never的时候,遇到了一个难题,never和C小加不在一块住,只能

HDOJ4540 威威猫系列故事——打地鼠 【DP】

威威猫系列故事--打地鼠 Time Limit: 300/100 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) Total Submission(s): 1445    Accepted Submission(s): 713 Problem Description 威威猫最近不务正业,每天沉迷于游戏"打地鼠". 每当朋友们劝他别太着迷游戏,应该好好工作的时候,他总是说,我是威威猫,猫打老鼠就是我的工作! 无话

NYOJ16 矩形嵌套 【DP】

矩形嵌套 时间限制:3000 ms  |  内存限制:65535 KB 难度:4 描述 有n个矩形,每个矩形可以用a,b来描述,表示长和宽.矩形X(a,b)可以嵌套在矩形Y(c,d)中当且仅当a<c,b<d或者b<c,a<d(相当于旋转X90度).例如(1,5)可以嵌套在(6,2)内,但不能嵌套在(3,4)中.你的任务是选出尽可能多的矩形排成一行,使得除最后一个外,每一个矩形都可以嵌套在下一个矩形内. 输入 第一行是一个正正数N(0<N<10),表示测试数据组数, 每组

hdoj 2046 骨牌铺方格 【DP】+【斐波那契】

dp果然不是好学的... 第n个,即2*n时,可由第n-1个的竖直排列再加一个,和第n-2个中横着排两个 所以f(n) = 1×f(n-1) + 1×f(n-2): 骨牌铺方格 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 28412    Accepted Submission(s): 13771 Problem Descripti