[动态规划] LCIS

描述 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.



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值