zoukankan      html  css  js  c++  java
  • bzoj1855

    让我们继续练习dp

    首先这道题约束条件很多

    但实际上方程还是很好写的,f[i,j]表示第i天时拥有j只股票的最大收益

    令p=max(0,i-k-1) 上一次较交易

    易得f[i,j]=max(f[i-1,j],f[p,j-b]-ap[i]*b,f[p,j+s]+bp[i]*s) b<=as[i],s<=bs[i];

    显然会TLE,我们要优化

    f[i-1,j]我们可以先不管他,

    我们令j1=j-b  j2=j+s

    则max(0,j-as[i])<=j1<=j

      j<=j2<=min(m,j+bs[i]);

    则原式可化为

    f[i,j]=max(f[p,j1]+ap[i]*j1-ap[i]*j,f[p,j2]+bp[i]*j2-bp[i]*j)

    观察得知对于当前的状态,结果只与j1,j2有关系

    于是我们可以分开来对j1,j2求区间最大,再求一个总的最大就行

     对此我们可以用线段树

    但是,线段树算法O(n^2logn)而且实际常数较大,会TLE(一开始我就是这样)

    观察区间其实总是整体右移的,这很像我一开始做的单调队列的滚动窗口那道题

    于是我们可以用单调队列优化

    加入只考虑买入的情况对于k1<k2

    如果有f[p,k2]+ap[i]*k2>=f[p,k2]+ap[i]*k2 那么k2一定比k1优(更可能成为区间最大)

    卖出情况同理,因此我们从0~m遍历一边,维护一个单调减的队列就行了

    每个点最多出队一次,入队一次

    因此复杂度为O(n^2);

     1 const inf=-100000007;
     2 var q,b,s,ns,nb,vs,vb:array[0..2010] of longint;
     3     f:array[0..2010,0..2010] of longint;
     4     l,ans,h,t,p,i,j,k,n,m:longint;
     5 
     6 function max(a,b:longint):longint;
     7   begin
     8     if a>b then exit(a) else exit(b);
     9   end;
    10 
    11 function compareb(x,y:longint):boolean;
    12   begin
    13     if f[p,x]+vb[i]*x>=f[p,y]+vb[i]*y then exit(true) else exit(false);
    14   end;
    15 
    16 function compares(x,y:longint):boolean;
    17   begin
    18     if f[p,x]+vs[i]*x>=f[p,y]+vs[i]*y then exit(true) else exit(false);
    19   end;
    20 
    21 begin
    22   readln(n,m,k);
    23   for i:=1 to n do
    24     readln(vb[i],vs[i],nb[i],ns[i]);
    25   for i:=1 to m do
    26     f[0,i]:=inf;
    27   f[0,0]:=0;
    28   for i:=1 to n do
    29   begin
    30     p:=max(i-k-1,0);
    31     h:=0;
    32     t:=0;
    33     q[0]:=0;
    34     for j:=0 to m do   //买入情况
    35     begin
    36       if j<>0 then
    37       begin
    38         while (h<t) and compareb(j,q[t]) do dec(t);
    39         inc(t);
    40         q[t]:=j;
    41       end;
    42       l:=max(0,j-nb[i]);
    43       while (q[h]<l) do inc(h);
    44       while (h<t) and compareb(q[h+1],q[h]) do inc(h);
    45       b[j]:=f[p,q[h]]+vb[i]*q[h];
    46     end;
    47     h:=0;
    48     t:=0;
    49     q[0]:=m;
    50     for j:=m downto 0 do   //卖出情况
    51     begin
    52       if j<>m then
    53       begin
    54         while (h<t) and compares(j,q[t]) do dec(t);
    55         inc(t);
    56         q[t]:=j;
    57       end;
    58       l:=j+ns[i];
    59       if l>m then l:=m;
    60       while (q[h]>l) do inc(h);
    61       while (h<t) and compares(q[h+1],q[h]) do inc(h);
    62       s[j]:=f[p,q[h]]+vs[i]*q[h];
    63     end;
    64     for j:=0 to m do   //求总的最大
    65       f[i,j]:=max(f[i-1,j],max(b[j]-vb[i]*j,s[j]-vs[i]*j));
    66   end;
    67   ans:=f[n,0];   //显然手上无股票最合算
    68   writeln(ans);
    69 end.
    View Code
  • 相关阅读:
    jsp 接收汉字参数乱码
    文件下载汉字乱码
    服务器端汉字乱码
    SpringMVC + ajax
    Java正确URL解码方式:URLDecoder.decode
    spring MVC 文件上传错误
    json
    android 带checkbox的List
    Incorrect string value: 'xE8x8Bx8FxE6x99xA8...' for column 'user_name' at row 1
    django初探-创建简单的博客系统(一)
  • 原文地址:https://www.cnblogs.com/phile/p/4473236.html
Copyright © 2011-2022 走看看