E50 单调队列优化DP 股票交易

视频链接:458 单调队列优化DP 股票交易_哔哩哔哩_bilibili

Luogu P2569 [SCOI2010]股票交易

时间:O(T*P)

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

const int N=2010;
int T,maxP,W;     //天数T,股票最大拥有数maxP,间隔W天
int ap,bp,as,bs;  //买入价ap,卖出价bp,买入数as,卖出数bs
int f[N][N],q[N]; //f[i][j]表示第 i 天后,拥有 j 张股票的最大收益

int main(){
  scanf("%d%d%d",&T,&maxP,&W);
  memset(f,-0x3f,sizeof(f));
  for(int i=1;i<=T;i++){        //枚举天数
    scanf("%d%d%d%d",&ap,&bp,&as,&bs);
    for(int j=0;j<=as;j++) f[i][j]=-ap*j; //凭空买
    for(int j=0;j<=maxP;j++)f[i][j]=max(f[i][j],f[i-1][j]);//不买不卖
    if(i<=W) continue;          //不能转移就跳过
    int h=1,t=0;
    for(int j=0;j<=maxP;j++){   //买入(窗口右滑)
      while(h<=t && f[i-W-1][q[t]]+ap*q[t]<=f[i-W-1][j]+ap*j) t--;
      q[++t]=j;
      if(q[h]<j-as) h++;
      f[i][j]=max(f[i][j],f[i-W-1][q[h]]-ap*(j-q[h])); 
    }
    h=1,t=0;
    for(int j=maxP;j>=0;j--){   //卖出(窗口左滑)
      while(h<=t && f[i-W-1][q[t]]+bp*q[t]<=f[i-W-1][j]+bp*j) t--;
      q[++t]=j;
      if(q[h]>j+bs) h++;
      f[i][j]=max(f[i][j],f[i-W-1][q[h]]+bp*(q[h]-j));
    } 
  }
  printf("%d",f[T][0]);
}
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

const int N=2010;
int T,maxP,W;     //天数T,股票最大拥有数maxP,间隔W天
int ap,bp,as,bs;  //买入价ap,卖出价bp,买入数as,卖出数bs
int f[N][N],q[N]; //f[i][j]表示第 i 天后,拥有 j 张股票的最大收益

int main(){
  scanf("%d%d%d",&T,&maxP,&W);
  memset(f,-0x3f,sizeof(f));
  for(int i=1;i<=T;i++){        //枚举天数
    scanf("%d%d%d%d",&ap,&bp,&as,&bs);
    for(int j=0;j<=as;j++) f[i][j]=-ap*j; //凭空买
    for(int j=0;j<=maxP;j++)f[i][j]=max(f[i][j],f[i-1][j]);//不买不卖
    if(i<=W) continue;          //不能转移就跳过
    int h=1,t=0;
    for(int j=0;j<=maxP;j++){   //买入(窗口右滑)
      while(h<=t && q[h]<j-as) h++;
      while(h<=t && f[i-W-1][q[t]]+ap*q[t]<=f[i-W-1][j]+ap*j) t--;
      q[++t]=j;
      f[i][j]=max(f[i][j],f[i-W-1][q[h]]-ap*(j-q[h])); 
    }
    h=1,t=0;
    for(int j=maxP;j>=0;j--){   //卖出(窗口左滑)
      while(h<=t && q[h]>j+bs) h++;
      while(h<=t && f[i-W-1][q[t]]+bp*q[t]<=f[i-W-1][j]+bp*j) t--;
      q[++t]=j;
      f[i][j]=max(f[i][j],f[i-W-1][q[h]]+bp*(q[h]-j));
    } 
  }
  printf("%d",f[T][0]);
}

 

练习:

POJ1821 Fence

POJ3017 Cut the Sequence

Luogu P2564 [SCOI2009]生日礼物

Luogu P2219 [HAOI2007]修筑绿化带

Luogu P3957 [NOIP2017 普及组] 跳房子

Luogu P1973 [NOI2011] NOI 嘉年华

Luogu P3229 [HNOI2013]旅行

 

posted @ 2023-04-29 14:20  董晓  阅读(259)  评论(0编辑  收藏  举报