JZOJ 4710 Value【NOIP2016提高A组模拟8.17】

Value

题目描述

这里写图片描述

数据范围

这里写图片描述

题解

一开始,先按照 w 数组的值从小到大排一下序,这样就能保证从前往后选时是最优的。
接下来,我们可以考虑动态规划,但是动态规划从前往后做的话我们就不知道后面选某个物品时他此时的价值为多少了。
所以我们倒着做。
F[i][ j ]表示物品i~ n 已经选择完毕,从中选了j件物品时的最大价值。
动态转移方程显然

F [i][ j ]=max(f[ k ][j- 1 ]-(j- 1 )*wi+ vi )(其中i< k<=n)

但是我们发现这个转移式是 O (n),那么总共的时间复杂度即为 O (n3)我们用一个后缀和维护一下,实现 O (1)转移,总的时间复杂度也就降为 O (n2)。

Code(Pascal)

var
    n,j,k,l,i,o,p:longint;
    ans:int64;
    w,v:array[0..10000] of int64;
    qz:array[0..6000] of int64; //后缀和数组
function max(a,b:int64):int64;
    begin
        if a>b then exit(a)
        else exit(b);
    end;
procedure sjzl;  //随机增量算法,防止快速排序时间超限
    var
        k,i:longint;
    begin
        randomize;
        for i:=1 to n div 2 do
        begin
            k:=random(n div 2)+1;
            w[0]:=w[i];
            w[i]:=w[i+k];
            w[i+k]:=w[0];
            v[0]:=v[i];
            v[i]:=v[i+k];
            v[i+k]:=v[0];
        end;
    end;
procedure qsort(l,r:longint);
    var
        i,j,m,mm:longint;
    begin
        i:=l;
        j:=r;
        m:=w[(l+r) div 2];
        mm:=v[(l+r) div 2];
        repeat
            while (w[i]<m) or ((w[i]=m) and (v[i]>mm)) do inc(i);
            while (w[j]>m) or ((w[j]=m) and (v[j]<mm)) do dec(j);
            if i<=j then
            begin
                w[0]:=w[i];
                w[i]:=w[j];
                w[j]:=w[0];
                v[0]:=v[i];
                v[i]:=v[j];
                v[j]:=v[0];
                inc(i);
                dec(j);
            end;
        until i>j;
        if l<j then qsort(l,j);
        if i<r then qsort(i,r);
    end;
begin
    readln(n);
    for i:=1 to n do
    readln(v[i],w[i]);
    sjzl;
    qsort(1,n);
    for i:=1 to n do
    qz[i]:=-maxlongint;
    for i:=n downto 1 do
    begin
        for l:=n-i downto 1 do
        qz[l+1]:=max(qz[l+1],qz[l]-w[i]*l+v[i]);
        qz[1]:=max(qz[1],v[i]);
    end;
    for i:=1 to n do
    ans:=max(ans,qz[i]);
    writeln(ans);
end.
  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值