当前位置: 代码迷 >> 综合 >> [bzoj1855][DP]股票交易
  详细解决方案

[bzoj1855][DP]股票交易

热度:15   发布时间:2023-12-19 05:16:14.0

Description

最近lxhgww又迷上了投资股票,通过一段时间的观察和学习,他总结出了股票行情的一些规律。
通过一段时间的观察,lxhgww预测到了未来T天内某只股票的走势,第i天的股票买入价为每股APi,第i天的股票卖出价为每股BPi(数据保证对于每个i,都有APi>=BPi),但是每天不能无限制地交易,于是股票交易所规定第i天的一次买入至多只能购买ASi股,一次卖出至多只能卖出BSi股。
另外,股票交易所还制定了两个规定。为了避免大家疯狂交易,股票交易所规定在两次交易(某一天的买入或者卖出均算是一次交易)之间,至少要间隔W天,也就是说如果在第i天发生了交易,那么从第i+1天到第i+W天,均不能发生交易。同时,为了避免垄断,股票交易所还规定在任何时间,一个人的手里的股票数不能超过MaxP。
在第1天之前,lxhgww手里有一大笔钱(可以认为钱的数目无限),但是没有任何股票,当然,T天以后,lxhgww想要赚到最多的钱,聪明的程序员们,你们能帮助他吗?

Input

输入数据第一行包括3个整数,分别是T,MaxP,W。
接下来T行,第i行代表第i-1天的股票走势,每行4个整数,分别表示APi,BPi,ASi,BSi。

Output

输出数据为一行,包括1个数字,表示lxhgww能赚到的最多的钱数。

Sample Input

5 2 0

2 1 1 1

2 1 1 1

3 2 1 1

4 3 1 1

5 4 1 1

Sample Output

3

HINT

对于30%的数据,0 < =W 对于50%的数据,0 < =W 对于100%的数据,0 < =W 对于所有的数据,1 < =BPi <
=APi < =1000,1 < =ASi,BSi < =MaxP

题解

n4 n 4 的dp很显然,设 f[i][j] f [ i ] [ j ] 表示第i天拥有j的股票的最大收益,对于p有 p=[0,max(0,i?W?1)] p = [ 0 , m a x ( 0 , i ? W ? 1 ) ] ,有转移方程

f[i][j]=f[i?1][j] f [ i ] [ j ] = f [ i ? 1 ] [ j ]

f[i][j]=j?ASi<=k<jmax(f[p][k]?(j?k)?APi) f [ i ] [ j ] = ∑ j ? A S i <= k < j m a x ( f [ p ] [ k ] ? ( j ? k ) ? A P i )

f[i][j]=j<k<=j+BSimax(f[p][k]+(k?j)?BPi) f [ i ] [ j ] = ∑ j < k <= j + B S i m a x ( f [ p ] [ k ] + ( k ? j ) ? B P i )

考虑如何优化,此处仅考虑对于购买式,卖出式同样
即为 =max(f[p][k]+k?APi)?j?APi = m a x ( f [ p ] [ k ] + k ? A P i ) ? j ? A P i
由于 f[p][k] f [ p ] [ k ] p p 单调递增的情况下单调不减
发现对于任意k都可以容易维护一个最大值 f [ p ] [ k ] + k ? A P i
复杂度降为 n?maxP2 n ? m a x P 2
又发现对于任意j,j-ASi单调递增
故可以单调队列优化
再次降为 n?maxP n ? m a x P

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
struct node{
   int APi,BPi,ASi,BSi;}a[2005];
int T,mxP,W;
int li[2005],g[2005];
int mx[2005],f[2005][2005];
bool vis[2005][2005];
/* f[p][k] max(l1) max(l2) */
int h,t;
int main()
{scanf("%d%d%d",&T,&mxP,&W);for(int i=1;i<=T;i++)scanf("%d%d%d%d",&a[i].APi,&a[i].BPi,&a[i].ASi,&a[i].BSi);int p;memset(f,-63,sizeof(f));memset(vis,false,sizeof(vis));f[0][0]=0;vis[0][0]=true;for(int i=1;i<=T;i++){for(int j=0;j<=mxP;j++)if(vis[i-1][j])f[i][j]=f[i-1][j],vis[i][j]=true;p=max(0,i-W-1);h=t=1;li[1]=0;for(int j=0;j<=mxP;j++){while(h<t && j-a[i].ASi>li[h])h++;if(h<=t && j-a[i].ASi<=li[h])f[i][j]=max(f[i][j],f[p][li[h]]-(j-li[h])*a[i].APi),vis[i][j]=true;if(vis[p][j]){while(h<=t && f[p][j]+j*a[i].APi>f[p][li[t]]+li[t]*a[i].APi)t--;li[++t]=j;}}h=t=1;li[1]=mxP;for(int j=mxP;j>=0;j--){while(h<t && li[h]>j+a[i].BSi)h++;if(h<=t && j+a[i].BSi>=li[h])f[i][j]=max(f[i][j],f[p][li[h]]+(li[h]-j)*a[i].BPi),vis[i][j]=true;if(vis[p][j]){while(h<=t && f[p][j]+j*a[i].BPi>f[p][li[t]]+li[t]*a[i].BPi)t--;li[++t]=j;}}}int ans=0;for(int i=0;i<=mxP;i++)ans=max(ans,f[T][i]);printf("%d\n",ans);return 0;
}