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
题解
的dp很显然,设 表示第i天拥有j的股票的最大收益,对于p有 ,有转移方程
考虑如何优化,此处仅考虑对于购买式,卖出式同样
即为
由于 在 单调递增的情况下单调不减
发现对于任意k都可以容易维护一个最大值
复杂度降为
又发现对于任意j,j-ASi单调递增
故可以单调队列优化
再次降为
#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;
}