E50 单调队列优化DP 股票交易
视频链接:458 单调队列优化DP 股票交易_哔哩哔哩_bilibili
时间: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]); }
练习:
Luogu P3957 [NOIP2017 普及组] 跳房子