【BZOJ1855】[Scoi2010] 股票交易
很显然的动态规划题(笑)
容易想到DP的数组 f[i][j] 表示第i天手上有j股股票时能赚到最多的钱。
接下来就是转移了,有这么多变量一定要看清楚,仔细地分情况讨论。
每次转移时一共有四种情况:
(先从简单的入手)
一、第i天不买股票也不买
那就是从前一天相同的股票值更新过来
f[i][j]=max(f[i][j],f[i-1][j]);
那为什么是前一天而不是前几天呢?因为前几天的最优值都已经更新到前一天了呀。
二、第i天凭空买股票(相当于从之前手持0股票的情况更新来)
其实就是第i天的DP数组的初始化
For(j,0,As[i]) f[i] [j]=-1 * j * Ap[i];
三、第i天在第 i-w-1 天的基础上买股票
那我们设第i-w-1天的股票数为k,最直接的更新就是下面这样
f[i][j]=max(f[i][j], f[i-w-1][k]-(j-k)* Ap[i]);
但我们此时要更新的是j,所以可以稍稍转化一下:
f[i][j]=max{ f[i-w-1][k]+k*Ap[i] } - j* Ap[i]
那么此时k的范围是多少呢 不难想到就是 [ j-As[i], j)
所以在k的取值范围上,有经验的OIer们应该都能想到单调队列了吧(!)
式子中有取max值,还有取值范围的经常都是用单调队列来优化(不知道具体如何操作的可以看代码)
四、第i天在第i-w-1天的基础上卖出股票
和上一种情况其实是一样的(式子的推导请参照上式自己操作)
f[i][j]=max{f[i-w-1][k]+k*Bp[i]}- j* Ap[i]
只是k的取值范围不一样了,变成了(j, j+Bs[i] ]
同样可以用单调队列来优化。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 #include<algorithm> 6 7 #define For(i,a,b) for(register int i=a;i<=b;++i) 8 #define Dwn(i,a,b) for(register int i=a;i>=b;--i) 9 #define Re register 10 11 using namespace std; 12 13 const int N=2e3+10; 14 int f[N][N],q[N*2],qf,qr; 15 int n,m,As[N],Ap[N],Bs[N],Bp[N],W,T,MaxP; 16 inline void read(int &v){ 17 v=0; 18 char c=getchar(); 19 while(c<'0'||c>'9')c=getchar(); 20 while(c>='0'&&c<='9')v=v*10+c-'0',c=getchar(); 21 } 22 int main(){ 23 read(T); read(MaxP); read(W); 24 For(i,1,T){ 25 read(Ap[i]); read(Bp[i]); 26 read(As[i]); read(Bs[i]); 27 } 28 memset(f,128,sizeof(f)); 29 For(i,1,T){ 30 // I bought some stocks from nowhere 31 For(j,0,As[i]){ 32 f[i][j]=-1*j*Ap[i]; 33 } 34 // I didn't buy anything 35 For(j,0,MaxP){ 36 f[i][j]=max(f[i][j],f[i-1][j]); 37 } 38 39 if(i-W-1<=0)continue; 40 41 // I bought some stock today after W days 42 qf=1; qr=0; 43 For(j,0,MaxP){ 44 while(qf<=qr&&q[qf]<j-As[i])qf++; 45 if(qf<=qr){ 46 int k=q[qf]; 47 f[i][j]=max(f[i][j],f[i-W-1][k]+k*Ap[i]-j*Ap[i]); 48 } 49 while(qf<=qr&&f[i-W-1][q[qr]]+q[qr]*Ap[i]<=f[i-W-1][j]+j*Ap[i])qr--; 50 q[++qr]=j; 51 } 52 53 // I sold some stock today after W days 54 qf=1; qr=0; 55 Dwn(j,MaxP,0){ 56 while(qf<=qr&&q[qf]>j+Bs[i])qf++; 57 if(qf<=qr){ 58 int k=q[qf]; 59 f[i][j]=max(f[i][j],f[i-W-1][k]+k*Bp[i]-j*Bp[i]); 60 } 61 while(qf<=qr&&f[i-W-1][q[qr]]+q[qr]*Bp[i]<=f[i-W-1][j]+j*Bp[i])qr--; 62 q[++qr]=j; 63 } 64 } 65 int fn=-2147483600; 66 For(i,0,MaxP)fn=max(fn,f[T][i]); 67 cout<<fn<<endl; 68 return 0; 69 }