【BZOJ】1855: [Scoi2010]股票交易-队列优化DP

版权声明:转载请附带链接或评论 https://blog.csdn.net/corsica6/article/details/82356503

传送门:bzoj1855


题解

f [ i ] [ j ] ( 1 i n , 0 j M a x P ) 为第 i 天结束,手里有 j 股股票的最大利益,对于第 x 天的情况,分四种情况讨论:

  • 净买入 k ( 0 k A S x ) 股, f [ x ] [ k ] = A P x × k
  • 不买不卖, f [ x ] [ k ] = f [ x 1 ] [ k ] ( 0 k M a x P )
  • 在原来的基础上买入: f [ x ] [ k ] = m a x j = 1 x m 1 ( m a x t = 1 k ( f [ j ] [ k t ] t × A P x ) ) ,
  • 在原来的基础上卖出: f [ x ] [ k ] = m a x j = 1 x m 1 ( m a x t = 1 M a x P k ( f [ j ] [ k + t ] + t × B P x ) )

四种情况取 m a x 转移即可。

由于对于特定的 j f [ i ] [ j ] ( 1 i n ) 是单调不下降的,所以简化后两个转移式为:
f [ x ] [ k ] = m a x t = 1 k ( f [ x m 1 ] [ k t ] t × A P x ) = m a x t = 1 k ( f [ x m 1 ] [ k t ] + ( k t ) × A P x ) k × A P x

f [ x ] [ k ] = m a x t = 1 M a x P k ( f [ x m 1 ] [ k + t ] + t × B P x ) = m a x t = 1 M a x P k ( f [ x m 1 ] [ k + t ] + ( k + t ) × B P x ) k × B P x

单调队列优化即可。


代码

#include<bits/stdc++.h>
#define gc getchar()
#define si isdigit(c)
#define RI register
using namespace std;
const int N=2020;
int n,m,w,ap,bp,as,bs;
int q[N],l,r,f[N][N],ans;

char c;
inline void rd(int &x)
{
    c=gc;x=0;int f=0;
    for(;!si;c=gc) if(c=='-') f=1;
    for(;si;c=gc) x=x*10+(c^48);
    if(f) x=-x;
}

int main(){
    RI int i,j;
    memset(f,128,sizeof(f));
    rd(n);rd(m);rd(w);
    for(i=1;i<=n;++i){
       rd(ap);rd(bp);rd(as);rd(bs);
       for(j=0;j<=as;++j) f[i][j]=-j*ap;
       for(j=0;j<=m;++j) f[i][j]=max(f[i][j],f[i-1][j]);
       if(i<=w) continue;
       l=1,r=0;
       for(j=0;j<=m;++j){
           for(;l<=r && q[l]<j-as;++l);
           for(;l<=r && f[i-w-1][q[r]]+q[r]*ap<=f[i-w-1][j]+j*ap;--r);
           q[++r]=j;
           if(l<=r) f[i][j]=max(f[i][j],f[i-w-1][q[l]]+(q[l]-j)*ap);
       }
       l=1,r=0;
       for(j=m;j>=0;--j){
           for(;l<=r && q[l]>j+bs;++l);
           for(;l<=r && f[i-w-1][q[r]]+q[r]*bp<=f[i-w-1][j]+j*bp;--r);
           q[++r]=j;
           if(l<=r) f[i][j]=max(f[i][j],f[i-w-1][q[l]]+(q[l]-j)*bp);
       }
    } 
    ans=-2e9;
    for(i=0;i<=m;++i) ans=max(ans,f[n][i]);
    printf("%d\n",ans);
}

猜你喜欢

转载自blog.csdn.net/corsica6/article/details/82356503
今日推荐