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
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.
Print the length of the longest common subsequence.
4 3 1 4 2 3 4 1 2 3 1 2 4 3
3
The answer for the first test sample is subsequence [1, 2, 3].
题解:这一题听说可以用DAG解,但是我不会.....
我的想法是既然每个数都只会出现一次,那我就用一个数组S[I][J]记录第I层的数J在I+1层的位置,再用D[I]记录以A[I]结尾的时候最长的长度。可以看到,如果把每个相同的数连起来,最长序列中是不存在相交的线段的,所以我们就可以得到递推方程:
D[I]=max(D[J]+1,D[I]) (条件:数I的连线和J的连线不相交)
条件可以用数组S来判断,这样这个问题就成了“最长不下降子序列”的形状。最后找出D[I]的最大值即可。
#include <iostream>
#include <cstdio>
using namespace std;
int s[10][1002],n,k,i,ans,j,a[7][1002],d[1002];
int _check(int i,int j)
{
int de=1,x=i,y=j;
while (s[de][a[de][x]]>s[de][a[de][y]] && de<k)
{
x=s[de][a[de][x]];
y=s[de][a[de][y]];
de++;
}
if (de==k) return 1;
else return 0;
}
int main()
{
scanf("%d%d",&n,&k);
for (int i=1;i<=k;i++)
for (int j=1;j<=n;j++)
{
scanf("%d",&a[i][j]);
s[i-1][a[i][j]]=j;
}
for (int i=1;i<=n;i++) d[i]=1;
for (int i=1;i<=n;i++)
for (int j=1;j<i;j++)
if (_check(i,j)) d[i]=max(d[j]+1,d[i]);
for (int i=1;i<=n;i++) ans=max(ans,d[i]);
cout <<ans;
return 0;
}