Stock Trading - Monotone queue optimization DP

Title Description

 

 Thinking

  Konjac still too weak ,, think half the equation on GG, as to what can not think of a more monotonous queue.

  $ F [i] [j] $ $ i represents the biggest days of gains j $ Zhang stock.

  So there are four options:

  1. Not buy stocks: $ f [i] [j] = max (f [i] [j], f [i-1] [j]) $
  2. Buy $ j $ Zhang stock, did not buy before: $ f [i] [j] = - j * ap [i] $
  3. Buy $ J $ sheet stock, had before the transaction, an interval of the $ W $ days: $ f [i] [j] = max (f [i] [j], f [iw-1] [k] - ( jk) * ap [i]) $
  4. Buy $ J $ sheet stock, had a transaction (nonsense) before, an interval of the $ W $ day, $ f [i] [j] = max (f [i] [j], f [iw-1] [k ] + (kj) * bp [i]) $

  Listed equations, or well understood. So how to optimize it? We found that $ i, j, k $ must enumerate $ O (n ^ 3) $ complexity will of $ T $, we need to use some optimization.

  We find: 3 Transfer $ f [iw-1] [k] - (jk) * ap [i] = f [iw-1] [k] + k * ap [i] -j * ap [i] $ so long as we find the maximum of $ f [iw-1] [k] + k * ap [i] $ i to the first day, because the first two-dimensional $ i, j $ known, $ j * ap [ I] $ is a constant.

  With a monotonically decreasing queue maintains that the $ f [iw-1] [ k] + k * ap [i] $ $ K $ largest, each taking the first team to transfer, if attention $ as [i] <jk when $ (that is, not so much to buy stock), you need to pop the first team. 4 is the same then, maintaining maximum $ f [iw-1] [ k] + k * bp [i] (bs [i] <kj) $

code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int N=2010;
int n,m,w,ap,bp,as,bs;
int f[N][N],q[N],head,tail;

int main()
{
    scanf("%d%d%d",&n,&m,&w);
    memset(f,128,sizeof(f));//负无穷 
    for(int i=1;i<=n;i++)
    {
        scanf("%d%d%d%d",&ap,&bp,&as,&bs);
        for(int j=0;j<=as;j++)f[i][j]=-ap*j;//转移2 
        for(int j=0;j<=m;j++)f[i][j]=max(f[i-1][j],f[i][j]);//转移1 
        if(i<=w)continue;//之前不能进行交易 
        head=1,tail=0;
        for(int j=0;j<=m;j++)
        {
            while(head<=tail&&q[head]<j-as)
            head++;//不够买 
            while(head<=tail&&f[i-w-1][q[tail]]+q[tail]*ap<=f[i-w-1][j]+j*ap)
            tail--;//单调性 
            q[++tail]=j;//加入新元素 
            if(head<=tail)
            f[i][j]=max(f[i][j],f[i-w-1][q[head]]+q[head]*ap-j*ap);//转移3 
        }
        head=1,tail=0;
        for(int j=m;j>=0;j--)
        {
            while(head<=tail&&q[head]>j+bs)
            head++;//不够卖 
            while(head<=tail&&f[i-w-1][q[tail]]+q[tail]*bp<=f[i-w-1][j]+j*bp)
            tail--;//单调性 
            q[++tail]=j;//加入新元素 
            if(head<=tail)
            f[i][j]=max(f[i][j],f[i-w-1][q[head]]+q[head]*bp-j*bp);//转移4 
        }
    }
    coutF << [n-] [ 0 ]; // the last day all sold is the optimal 
}
                

Guess you like

Origin www.cnblogs.com/THRANDUil/p/11605570.html