jzoj4762. 千帆渡

Description

在这里插入图片描述

Input

在这里插入图片描述

Output

在这里插入图片描述

Sample Input

输入1:
5
1 4 2 5 1
4
1 1 2 4
输入2:
见共享

Sample Output

输出1:
2
1 4
输出2:
见共享

Data Constraint

在这里插入图片描述

题解

此题是一道奇妙的题目。
由于各种原因,本题开捆绑数据,我想原因是为了防止大家水分水特别高。
所以我比赛时爆零了
正解真的要大开脑洞才行。
首先当然想到的是DP
设f[i,j]表示前i个红色的船,当前选到第j个蓝色的船的最大答案。
设g[i,j]表示上述情况下时,上一个蓝色的船是什么。
这样就可以边转移边记录答案了。
转移方程——
f[i,j]:=max(f[i−1,k]+1);g[i,j]:=k;[a[i]=b[j]]f[i,j]:=max(f[i-1,k]+1);g[i,j]:=k;[a[i]=b[j]]f[i,j]:=max(f[i1,k]+1);g[i,j]:=k;[a[i]=b[j]]
f[i,j]:=f[i−1,j];g[i,j]:=j;[a[i]&lt;&gt;b[j]]f[i,j]:=f[i-1,j];g[i,j]:=j;[a[i]&lt;&gt;b[j]]f[i,j]:=f[i1,j];g[i,j]:=j;[a[i]<>b[j]]
这样能够拿到45分的好成绩。

那么考虑优化。
由于这个k我们看起来很烦,那么考虑把一些冗杂的状态给减去。
我们设h[i,j]表示当前a[i]=b[j]时的f[i,j]状态下,由h[i,j]转移过来。
可以把h[i,j]想象成一个最优的k。
那么,每次在做完f[i,j]后,用当前的h[i+1,j-1]转移到h[i+1,j]即可。
具体就是分两类讨论——
1、当b[j]<a[i+1]且f[i,h[n+1,j-1]]<f[i,j]时,就更新h[i+1,j]=j
2、否则就是h[i+1,j]=h[i+1,j-1]
好好理解就懂了。

代码
{$inline on}
var
        i,j,k,l,n,m,ans,x,y,wz,gs,op,maxx,ni:longint;
        a,b,bb,id,ad,bd:array[0..5000] of longint;
        sum,map:array[1..5000,0..5000] of longint;
        f,g,h:array[0..5000,0..5000] of longint;
        answer:array[0..5000] of longint;

procedure qsort(l,r:longint);inline;
var
        i,j,k,m:longint;
begin
        i:=l;j:=r;
        m:=b[(l+r) div 2];
        repeat
                while b[i]<m do inc(i);
                while b[j]>m do dec(j);
                if i<=j then
                begin
                        k:=b[i];
                        b[i]:=b[j];
                        b[j]:=k;
                        k:=id[i];
                        id[i]:=id[j];
                        id[j]:=k;
                        inc(i);
                        dec(j);
                end;
        until i>j;
        if l<j then qsort(l,j);
        if r>i then qsort(i,r);
end;
function erfen(id,x,y:longint):longint;inline;
var
        l,r,mid:longint;
begin
        l:=x;
        r:=y;
        while l<r do
        begin
                mid:=(l+r)div 2;
                if sum[id,x]=sum[id,mid] then l:=mid+1 else r:=mid;
        end;
        erfen:=l;
end;
begin
        //assign(input,'qfd.in');reset(input);
        //assign(input,'0data.in');reset(input);
        readln(n);
        for i:=1 to n do
        begin
                read(a[i]);
        end;
        readln(m);
        for i:=1 to m do
        begin
                read(b[i]);
        end;
        for i:=1 to n do
        begin
                for j:=1 to m do
                begin
                        if a[i]=b[j] then
                        begin
                                //for k:=0 to j-1 do
                                begin
                                        if (b[h[i,j]]<b[j]) and (f[i,j]<f[i-1,h[i,j]]+1) then
                                        begin
                                                f[i,j]:=f[i-1,h[i,j]]+1;
                                                g[i,j]:=h[i,j];
                                        end;
                                end;
                        end
                        else
                        begin
                                f[i,j]:=f[i-1,j];
                                g[i,j]:=j;
                        end;

                        ni:=i+1;
                        if b[j]<a[ni] then
                        begin
                                if f[i,h[ni,j-1]]>=f[i,j] then
                                begin
                                        h[ni,j]:=h[ni,j-1];
                                end
                                else
                                begin
                                        h[ni,j]:=j;
                                end;
                        end
                        else
                        begin
                                h[ni,j]:=h[ni,j-1];
                        end;
                end;
        end;
        for i:=1 to n do
        begin
                for j:=1 to m do
                begin
                        if ans<f[i,j] then
                        begin
                                x:=i;
                                y:=j;
                                ans:=f[i,j];
                        end;
                end;
        end;
        writeln(ans);
        while x>0 do
        begin
                if a[x]=b[y] then
                begin
                        inc(answer[0]);
                        answer[answer[0]]:=a[x];
                end;
                y:=g[x,y];
                x:=x-1;
        end;
        for i:=answer[0] downto 1 do
        begin
                write(answer[i],' ');
        end;
        writeln;
end.

转载于:https://www.cnblogs.com/RainbowCrown/p/11148374.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值