1. 题目
配饰(ornament)
【问题描述】
但是小L想考验一下小T,所以,他给小T出了一个难题.
他拿出了他所有的配饰并摆成两列,如果两个配饰的型号一样并且出现在不同列中,那么我们就可以认为这两个配饰为情侣配饰.另外,由于某些不为人知的原因,我们规定,在顺序选取的情况下,每选定的一对配饰必须比前面选定的一对配饰的型号要大.小T最多能够选取多少对配饰呢?
【输入格式】
共四行
第一行一个数N 表示第一列配饰的个数
第二行N个数 分别表示第一列配饰的型号
第三行一个数M 表示第二列配饰的个数
第四行M个数 分别表示第二列配饰的型号
【输出格式】
仅一个数K,表示最多能选取的情侣配饰的对数.
【样例输入】
5
1 4 2 6 8
5
1 5 0 2 4
【样例输出】
2
数据范围:
30%的数据 n,m<=10
70%的数据 n,m<=100
100%的数据 n,m<=5000
2. 算法
就是最长公共上升子序列(LCIS)的经典模型。
在这里,f[i]代表到a串的第i个数为止, 包括a[i]在内的并以a[i]为结尾的,与整个b串的最长公共上升子序列,其中max记录在a[i]>b[j]时a串的前i位与b串的前j位的LCIS,以便于下一个搜索到a[i]=b[j]时使用,此时使用的max时j之前的LCIS,把f[j]更新为max+1,这里的上一次求出的max为什么在a[i]=b[j]时也能使用呢?因为他们是相对于同一个a[i]来说的。因为a[i]<b[j]时,包括a[i]在内的LCIS不可能形成,所以不需要处理。
3. 注意事项
是公共上升子序列,而不是别的什么东西。
4. 代码
最长公共上升子序列(SueMiller)
var
n:longint;
a,b,f:array [1..5010] of longint;
procedure init;
var i:longint;
begin
readln(n);
for i:=1 to n do
read(a[i]);
readln;
for i:=1 to n do
read(b[i]);
readln;
end;
procedure dp;
var i,j,max:longint;
begin
fillchar(f,sizeof(f),0);
for i:=1 to n do
begin
max:=0;
for j:=1 to n do
if (b[j]<a[i]) and (f[j]>max) then max:=f[j]
else if (a[i]=b[j]) and (f[j]<max+1) then f[j]:=max+1;
end;
max:=0;
for i:=1 to n do
if f[i]>max then max:=f[i];
writeln(max);
end;
begin
assign(input,'ornament.in');reset(input);
assign(output,'ornament.out');rewrite(output);
init;
dp;
close(input);close(output);
end.