[动态规划] LCIS

来源:互联网 发布:linux文件系统管理 编辑:程序博客网 时间:2024/05/16 12:21
描述 Description
熊大妈的奶牛在小沐沐的熏陶下开始研究信息题目。小沐沐先让奶牛研究了最长上升子序列,再让他们研究了最长公共子序列,现在又让他们要研究最长公共上升子序列了。
小沐沐说,对于两个串A,B,如果它们都包含一段位置不一定连续的数字,且数字是严格递增的,那么称这一段数字是两个串的公共上升子串,而所有的公共上升子串中最长的就是最长公共上升子串了。
奶牛半懂不懂,小沐沐要你来告诉奶牛什么是最长公共上升子串。不过,只要告诉奶牛它的长度就可以了。
输入格式 InputFormat
第一行N,表示A,B的长度。
第二行,串A。
第三行,串B。
输出格式 OutputFormat
输出长度。
样例输入 SampleInput [复制数据]

样例输出 SampleOutput [复制数据]

数据范围和注释 Hint
1<=N<=3000,A,B中的数字不超过maxlongint
时间限制 TimeLimitation
各个测试点1s
来源 Source

Moe-ing



此题显然是一道动态规划的题目。难点在于状态的确定。


一开始想f[i,j]表示1..i,1..j的最长公共上升子串的长度。

发现转移方程试不好写,因为难以确定f[i,j]可以由什么推过来。


后来想f[i,j]表示1..i,1..j以 a[i],b[j] 为最长公共上升子串的最后的字符

发现转移方程依然不好写。。。


看题解后明白了此题解法。


f[i,j]表示1..i,以b[j]为最后字符的最长公共上升子串长度


f[i,j]=f[i-1,j]       //a[i]<>b[j]     

若f[i,j]>0 则1..i-1中必然存在k,使得a[k]=b[j] 

f[i-1,j]包含了a[k]


f[i,j]=max(f[i-1,k]+1), 0<=k<=j-1  //a[i]=b[j]

a[i]与b[j]配对成功,枚举之前的所有0<=k<=j-1

取里面的最大值来更新 f[i,j]

注意边界,b[0]:=0; 


虽然时间复杂度是(o^3)但是几乎遇不到能超时的数据


var n,ans:int64;    f:array[0..3000,0..3000]of int64;    a,b:array[0..3000]of int64;    i,j,k:longint;function max(a,b:int64):int64;begin    if a>b then exit(a) else exit(b);end;begin    readln(n);ans:=0;    fillchar(f,sizeof(f),0);    for i:=1 to n do  read(a[i]);readln;    for i:=1 to n do  read(b[i]);    b[0]:=0;    for i:=1 to n do    for j:=1 to n do    begin        if a[i]<>b[j] then f[i,j]:=f[i-1,j] else        begin            for k:=j-1 downto 0 do            if b[k]<b[j] then f[i,j]:=max(f[i,j],f[i-1,k]+1)        end;    end;    for i:=1 to n do //writeln(i,' ',f[n,i]);    ans:=max(ans,f[n,i]);    writeln(ans);    readln;readln;end.