http://codeforces.com/contest/463/problem/D
求k个序列的最长公共子序列。
k<=5
肯定 不能直接LCS
网上题解全是图论解法...我就来个dp的解法吧
首先,让我们创建的位置阵列的每个序列pos[k][N]。在这个数组,我们存储这n个数字(从1到n)在这k个序列中各个位置,然后按数大小排序。
DP [I]标记的最大长度共同序列,我们可以通过使用第一个序列的第i个元素生成。为此,我们遍历所有可能以前的编号(J),看看我们是否能延长DP [J]到DP [I]。
对于给定的J<I,只有在所有的序列中J的位置前与I,才能更新DP[I] = max(DP[J] + 1).
#include <cstdio> #include <cstdlib> #include <cmath> #include <cstring> #include <string> #include <queue> #include <vector> #include<set> #include <iostream> #include <algorithm> using namespace std; #define RD(x) scanf("%d",&x) #define RD2(x,y) scanf("%d%d",&x,&y) #define clr0(x) memset(x,0,sizeof(x)) typedef long long LL; vector <int> pos[1005]; int dp[1005]; int main() { int n,k,x; RD2(n,k); for(int i = 0;i < k;++i){ for(int j = 1;j <= n;++j){ RD(x); pos[x].push_back(j); } } sort(pos+1,pos+n+1); int ans = 1; for(int i = 1;i <= n;++i) dp[i] = 1; for(int i = 2;i <= n;++i){ for(int j = 1;j < i;++j){ bool ok = true; for(int l = 0;l < k;++l){ if(pos[j][l] > pos[i][l]){ ok = false; break; } } if(ok){ dp[i] = max(dp[j]+1,dp[i]); } } ans = max(ans,dp[i]); } printf("%d ",ans); return 0; }