UVA 111 - History Grading
这道dp题主要理解好题意:题中给的是按事项顺序的时间排列,而你要求的最长公共子序列是按时间顺序的事项排列,所以给你的排列要转化一下:例如:
10 3 1 2 4 9 5 10 6 8 7//意思是:1事项在第三个时间位置发生,2事项在第一个时间发生以此类推:转化为:2 3 1 4 6 8 10 9 5 7 1 2 3 4 5 6 7 8 9 10 4 7 2 3 10 6 9 1 5 8 3 1 2 4 9 5 10 6 8 7 2 10 1 3 8 4 9 5 7 6
代码如下:
#include<stdio.h>
#include<string.h>
#define MAXN 20+5
int n, T[MAXN],T1[MAXN], a[MAXN],a1[MAXN], f[MAXN][MAXN];
int compa, ord;
void change()
{
for(int i = 1; i <= n; i ++)
{
T1[T[i]] = i;
a1[a[i]] = i;
}
}
void dp()
{
ord = 0;
memset(f,0,sizeof(f));//printf("3\n");
for(int i = 1; i <= n; i ++)
for(int j = 1; j <= n; j ++)
{
if(T1[i] == a1[j]) f[i][j] = f[i-1][j-1] + 1;
else
{
if(f[i-1][j] < f[i][j-1]) f[i][j] = f[i][j-1];
else f[i][j] = f[i-1][j];
}
if(f[i][j] > ord) ord = f[i][j];
}
//ord = f[n][n];printf("ord=%d\n",ord);
}
void comp()
{
compa = 0;
for(int i = 1; i <= n; i ++)
if(a1[i] == T1[i]) compa ++;//printf("compa=%d\n",compa);
}
void input()
{
while(scanf("%d", &n) == 1)
{
memset(T,0,sizeof(T));
memset(a,0,sizeof(a));
for(int i = 1; i <= n; i ++)
scanf("%d",&T[i]);
for(;;)
{
for(int i = 1; i <= n; i ++)
if(scanf("%d",&a[i]) == EOF) return;
change();
comp();//printf("1\n");
dp();
if(compa > ord) printf("%d\n",compa);
else printf("%d\n",ord);
}
}
}
int main()
{
input();
return 0;
}