• 【BZOJ】【1855】【SCOI2010】/【HDOJ】【3401】股票交易


    DP/单调队列优化


      题解:http://www.cnblogs.com/jianglangcaijin/p/3799736.html

      令f[i][j]表示第 i 天结束后,手里剩下 j 股的最大利润,则有:

        [  f[i][j]= egin{cases} f[i-1][j] &   &{(不买不卖)}\ f[i-w-1][k]-ap[i]*(j-k)&   &{ j-as[i] leq k leq j-1 (买入)}\ f[i-w-1][k]+bp[i]*(k-j)&   &{ j+1 leq k leq j+bs[i] (卖出)} end{cases} ]

      对于买入,我们将式子变形得到:

        $$ f[i][j]=f[i-w-1][k]+ap[i]*k-ap[i]*j $$

      我们知道单调队列优化可以将形如 $ f[i]=max/min { f[k] }+g[i] $ 的式子中对k的枚举利用队列进行优化,这个式子中,"f[k]" 即是 $ f[i-w-1][k]+ap[i]*k $,“g[i]”即是 $ -ap[i]*j $,所以我们在枚举 j 的同时即可完成对k的维护(即每个f[i]都是一次单调队列优化下的DP)

      而卖出同理。

     1 /**************************************************************
     2     Problem: 1855
     3     User: Tunix
     4     Language: C++
     5     Result: Accepted
     6     Time:380 ms
     7     Memory:17068 kb
     8 ****************************************************************/
     9  
    10 //BZOJ 1855
    11 #include<cmath>
    12 #include<vector>
    13 #include<cstdio>
    14 #include<cstring>
    15 #include<cstdlib>
    16 #include<iostream>
    17 #include<algorithm>
    18 #define rep(i,n) for(int i=0;i<n;++i)
    19 #define F(i,j,n) for(int i=j;i<=n;++i)
    20 #define D(i,j,n) for(int i=j;i>=n;--i)
    21 #define pb push_back
    22 using namespace std;
    23 int getint(){
    24     int v=0,sign=1; char ch=getchar();
    25     while(ch<'0'||ch>'9'){ if (ch=='-') sign=-1; ch=getchar();}
    26     while(ch>='0'&&ch<='9'){ v=v*10+ch-'0'; ch=getchar();}
    27     return v*=sign;
    28 }
    29 const int N=2010,INF=~0u>>2;
    30 typedef long long LL;
    31 /******************tamplate*********************/
    32  
    33 struct node{
    34     int x,y;
    35     node(int _=0,int __=0):x(_),y(__){}
    36 }q[N];
    37 int f[N][N];
    38 int main(){
    39 #ifndef ONLINE_JUDGE
    40     freopen("1855.in","r",stdin);
    41     freopen("1855.out","w",stdout);
    42 #endif
    43     int n=getint(),m=getint(),w=getint();
    44     F(i,0,n) F(j,0,m) f[i][j]=-INF;
    45     int ans=0,ap,bp,as,bs;
    46     F(i,1,n){
    47         ap=getint(); bp=getint(); as=getint(); bs=getint();
    48         F(j,0,as) f[i][j]=-ap*j;
    49         F(j,0,m) f[i][j]=max(f[i][j],f[i-1][j]);
    50         int k=i-w-1;
    51         if (k>=0){
    52             int st=0,ed=0;
    53             F(j,0,m){
    54                 while(st<ed && q[st].x<j-as) st++;
    55                 while(st<ed && q[ed-1].y<=f[k][j]+ap*j) ed--;
    56                 q[ed++]=node(j,f[k][j]+ap*j);
    57                 if (st<ed) f[i][j]=max(f[i][j],q[st].y-ap*j);
    58             }
    59             st=ed=0;
    60             D(j,m,0){
    61                 while(st<ed && q[st].x>j+bs) st++;
    62                 while(st<ed && q[ed-1].y<=f[k][j]+bp*j) ed--;
    63                 q[ed++]=node(j,f[k][j]+bp*j);
    64                 if (st<ed) f[i][j]=max(f[i][j],q[st].y-bp*j);
    65             }
    66         }
    67         ans=max(ans,f[i][0]);
    68     }
    69     printf("%d
    ",ans);
    70     return 0;
    71 }
    View Code
  • 相关阅读:
    Linux系统挂载存储只读改成读写
    Linux kernel调试方法
    Linux设备树文件结构与解析深度分析
    #undef常用法
    Linux驱动中的platform总线分析
    在根文件系统中查看设备树(有助于调试)
    友元及操作符重载
    STM32 FLASH 擦除(以及防止误擦除程序代码)、写入
    C++学习笔记49:栈
    C++学习笔记48:链表的基本操作
  • 原文地址:https://www.cnblogs.com/Tunix/p/4321486.html
Copyright © 2020-2023  润新知