1. 程式人生 > >Codeforces 463D Gargari and Permutations(求k個序列的LCS)

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

std open sin problems name targe 題目 math 情況

題目鏈接: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<i),然後遍歷其他序列,如果對於每個序列k都滿足pos[k][a[1][i]]>pos[k][a[1][j]],

那麽說明a[1][i]可以接在a[1][j]後面,dp[a[1][i]]=max(dp[a[1][i],dp[a[1][j]]+1)。
這裏說明一下:按順序遍歷是為了保證dp[a[1][j]]是已經求好了的,如果直接按值來遍歷則會出現前面的dp值未求好的情況。

代碼:

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<algorithm>
 4 #include<vector>
 5 #include<string>
 6 #include<string.h>
 7
#include<cctype> 8 #include<math.h> 9 #include<stdlib.h> 10 #include<stack> 11 #include<queue> 12 #include<set> 13 #include<map> 14 #define lc(a) (a<<1) 15 #define rc(a) (a<<1|1) 16 #define MID(a,b) ((a+b)>>1) 17 #define fin(name) freopen(name,"r",stdin) 18
#define fout(name) freopen(name,"w",stdout) 19 #define clr(arr,val) memset(arr,val,sizeof(arr)) 20 #define _for(i,start,end) for(int i=start;i<=end;i++) 21 #define FAST_IO ios::sync_with_stdio(false);cin.tie(0); 22 using namespace std; 23 typedef long long LL; 24 const int N=2e3+5; 25 const LL INF64=1e18; 26 const int INF=0x3f3f3f3f; 27 const double eps=1e-10; 28 29 int dp[N],a[10][N],pos[10][N];//dp[i]表示以i結尾的最長公共子序列長度 30 31 int main(){ 32 FAST_IO; 33 int n,q; 34 cin>>n>>q; 35 for(int i=1;i<=q;i++){ 36 for(int j=1;j<=n;j++){ 37 cin>>a[i][j]; 38 pos[i][a[i][j]]=j; 39 } 40 } 41 42 for(int i=1;i<=n;i++){ 43 dp[a[1][i]]=1; 44 for(int j=1;j<i;j++){ 45 int t1=a[1][i],t2=a[1][j]; 46 bool flag=true; 47 for(int k=2;k<=q;k++){ 48 if(pos[k][t1]<=pos[k][t2]){ 49 flag=false; 50 break; 51 } 52 } 53 if(flag) 54 dp[t1]=max(dp[t1],dp[t2]+1); 55 } 56 } 57 58 int ans=1; 59 for(int i=1;i<=n;i++){ 60 ans=max(ans,dp[i]); 61 } 62 cout<<ans<<endl; 63 return 0; 64 }

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