zoukankan      html  css  js  c++  java
  • Codeforces 463D Gargari and Permutations:隐式图dp【多串LCS】

    题目链接:http://codeforces.com/problemset/problem/463/D

    题意:

      给你k个1到n的排列,问你它们的LCS(最长公共子序列)是多长。

     

    题解:

      因为都是1到n的排列,即每个串中,1到n每个数字恰好出现一次。

      将相同的数字之间相连,可以得到下面的样子(n = 4, k = 3):

      

      显然,要求的LCS就等于图中互不相交的最多连线个数。

      将每一个数字看做一个节点。

      若i到j有一条有向边,则代表:

        数字j的连线在i的连线的后面,且互不相交。

      即:

        若i->j,则要满足所有的pos[k][i] <= pos[k][j]。

        其中pos[k][i]表示第k个串中,数字i出现的位置。

      O(N^2*K)建图,最终得到的一定是一个有向无环图。

      LCS就等于这个图上的最长路径长度。

      所以dfs跑一边dp就行了。

    AC Code:

     1 #include <iostream>
     2 #include <stdio.h>
     3 #include <string.h>
     4 #include <vector>
     5 #define MAX_N 1005
     6 #define MAX_K 10
     7 
     8 using namespace std;
     9 
    10 int n,k;
    11 int dp[MAX_N];
    12 int a[MAX_K][MAX_N];
    13 int pos[MAX_K][MAX_N];
    14 vector<int> edge[MAX_N];
    15 
    16 void read()
    17 {
    18     cin>>n>>k;
    19     for(int i=1;i<=k;i++)
    20     {
    21         for(int j=1;j<=n;j++)
    22         {
    23             cin>>a[i][j];
    24             pos[i][a[i][j]]=j;
    25         }
    26     }
    27 }
    28 
    29 bool is_valid(int x,int y)
    30 {
    31     for(int i=1;i<=k;i++)
    32     {
    33         if(pos[i][x]>=pos[i][y]) return false;
    34     }
    35     return true;
    36 }
    37 
    38 void build()
    39 {
    40     for(int i=1;i<=n;i++)
    41     {
    42         for(int j=1;j<=n;j++)
    43         {
    44             if(is_valid(i,j)) edge[i].push_back(j);
    45         }
    46     }
    47 }
    48 
    49 void dfs(int now)
    50 {
    51     dp[now]=1;
    52     for(int i=0;i<edge[now].size();i++)
    53     {
    54         int temp=edge[now][i];
    55         if(dp[temp]==-1) dfs(temp);
    56         dp[now]=max(dp[now],dp[temp]+1);
    57     }
    58 }
    59 
    60 void work()
    61 {
    62     build();
    63     memset(dp,-1,sizeof(dp));
    64     int ans=0;
    65     for(int i=1;i<=n;i++)
    66     {
    67         if(dp[i]==-1) dfs(i);
    68         ans=max(ans,dp[i]);
    69     }
    70     cout<<ans<<endl;
    71 }
    72 
    73 int main()
    74 {
    75     read();
    76     work();
    77 }
  • 相关阅读:
    【读书笔记】深入理解计算机系统
    快速排序
    列表查找的两种方法
    冒泡排序、选择排序、插入排序
    堆排序
    supervisor进程管理
    redis-主从复制
    redis-淘汰策略
    URI和URL
    python爬虫之xpath的基本使用
  • 原文地址:https://www.cnblogs.com/Leohh/p/8244662.html
Copyright © 2011-2022 走看看