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

DP/单调队列优化


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

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

    \[  f[i][j]= \begin{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\n",ans);
70     return 0;
71 }
View Code

 

posted @ 2015-03-08 11:53  Tunix  阅读(528)  评论(0编辑  收藏  举报