• 单调队列优化DP || [SCOI2010]股票交易 || BZOJ 1855 || Luogu P2569


    题面:P2569 [SCOI2010]股票交易

    题解:

    F[i][j]表示前i天,目前手中有j股的最大收入
    Case 1:第i天是第一次购买股票
    F[i][j]=-j*AP[i]; (1<=j<=AS[i])
    Case 2:第i天没有购买股票
    F[i][j]=max(F[i][j],F[i-1][j])
    Case 3:第i天买入j-k股
    因为F[i][j]的最优情况是会顺承的,所以如果
    第i天有交易的话,直接从第i-W-1天进行转移即可
    F[i][j]=max(F[i][j],F[i-W-1][k]-AP[i]*(j-k))
    (1<=j-k<=AS[i],i-W-1>=1)
    Case 4:第i天卖出k-j股
    F[i][j]=max(F[i][j],F[i-W-1][k]+BP[i]*(k-j))
    (1<=k-j<=BS[i],i-W-1>=1)
    再使用单调队列进行维护


    所以对于Case 3:
    找出max(F[i-W-1][k]+AP[i]*k)-AP[i]*j (1<=j-k<=AS[i],i-W-1>=1)
    j-AS[i]<=k<=j-1,i-W-1>=1

    对于Case 4:
    找出max(F[i-W-1][k]+BP[i]*k)-BP[i]*j (1<=j-k<=BS[i],i-W-1>=1)
    1+j<=k<=BS[i]+j,i-W-1>=1

    额外:鸣谢@QZZ帮我解答了一个傻逼问题。

    代码:

     1 #include<cstdio>
     2 #include<queue>
     3 #define min(a,b) ((a)<(b)?(a):(b))
     4 #define max(a,b) ((a)>(b)?(a):(b))
     5 using namespace std;
     6 const int maxn=2050,inf=1<<30;
     7 int T,MaxP,W,F[maxn][maxn],AP[maxn],BP[maxn],AS[maxn],BS[maxn];
     8 struct Node{ int k,data; }nd;
     9 Node que[maxn];
    10 int f1,f2,ans;
    11 int main(){
    12     scanf("%d%d%d",&T,&MaxP,&W);
    13     for(int i=1;i<=T;i++)
    14         scanf("%d%d%d%d",&AP[i],&BP[i],&AS[i],&BS[i]);
    15        for(int i=0;i<=T;i++)
    16         for(int j=0;j<=MaxP;j++){
    17             if(j<=AS[i]) F[i][j]=-j*AP[i];
    18             else F[i][j]=-inf;
    19         }
    20     for(int i=1;i<=T;i++){
    21         for(int j=0;j<=MaxP;j++) F[i][j]=max(F[i][j],F[i-1][j]);
    22         if(i-W-1>=0){
    23             int w=i-W-1;
    24             f1=1;f2=0;
    25             for(int j=0;j<=MaxP;j++){                
    26                 while(f1<=f2 && que[f1].k<j-AS[i]) f1++;
    27                 if(f1<=f2) F[i][j]=max(F[i][j],que[f1].data-AP[i]*j);
    28                 while(f1<=f2 && F[w][j]+AP[i]*j>=que[f2].data) f2--;
    29                 que[++f2].k=j; que[f2].data=F[w][j]+AP[i]*j;
    30             }
    31             f1=1;f2=0;
    32             for(int j=MaxP;j>=0;j--){                
    33                 while(f1<=f2 && que[f1].k>j+BS[i]) f1++;
    34                 if(f1<=f2) F[i][j]=max(F[i][j],que[f1].data-BP[i]*j);
    35                 while(f1<=f2 && F[w][j]+BP[i]*j>=que[f2].data) f2--;
    36                 que[++f2].k=j; que[f2].data=F[w][j]+BP[i]*j;
    37             }
    38         }
    39     }
    40     ans=-inf;
    41     for(int i=0;i<=MaxP;i++) ans=max(ans,F[T][i]);
    42     printf("%d
    ",ans);
    43     return 0;
    44 }

    By:AlenaNuna

  • 相关阅读:
    如何区分DDR1 DDR2 DDR3内存条
    《闪电战》德军攻略
    WINDOWS SERVER 2008 R2安装指南
    【django】django学得好迷茫啊 来个学习规划吧
    【阅读】提问的智慧+有效的报告BUG
    【Python】logging模块学习笔记
    【接口测试】进度表
    【django】django深入学习笔记
    【随笔】2014工作总结
    【英语】Bingo口语笔记(47)
  • 原文地址:https://www.cnblogs.com/AlenaNuna/p/11556677.html
Copyright © 2020-2023  润新知