[单调队列]股票交易

股 票 交 易 股票交易


题目描述

最近 lxhgww又迷上了投资股票,通过一段时间的观察和学习,他总结出了股票行情的一些规律。

通过一段时间的观察,lxhgww 预测到了未来 T 天内某只股票的走势,第 i 天的股票买入价为每股 APi​,第 i 天的股票卖出价为每股 BPii​(数据保证对于每个 i,都有 APi≥BPi),但是每天不能无限制地交易,于是股票交易所规定第 i 天的一次买入至多只能购买 ASi 股,一次卖出至多只能卖出 BSi 股。

另外,股票交易所还制定了两个规定。为了避免大家疯狂交易,股票交易所规定在两次交易(某一天的买入或者卖出均算是一次交易)之间,至少要间隔 W 天,也就是说如果在第 i 天发生了交易,那么从第 i+1 天到第 i+W 天,均不能发生交易。同时,为了避免垄断,股票交易所还规定在任何时间,一个人的手里的股票数不能超过 MaxP。

在第 111 天之前,lxhgww 手里有一大笔钱(可以认为钱的数目无限),但是没有任何股票,当然,T 天以后,lxhgw 想要赚到最多的钱,聪明的程序员们,你们能帮助他吗?


输入

输入数据第一行包括 3 个整数,分别是 T,MaxP,W。

接下来 T 行,第 i 行代表第 i−1 天的股票走势,每行 4 个整数,分别表示 APi, BPi, ASi, BSi​。


输出

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


样例输入

5 2 0
2 1 1 1
2 1 1 1
3 2 1 1
4 3 1 1
5 4 1 1


样例输出

3


数据范围

对于 30% 的数据,0≤W<T≤50,1≤MaxP≤50

对于 50% 的数据,0≤W<T≤2000,1≤MaxP≤50

对于 100% 的数据,0≤W<T≤2000,1≤MaxP≤2000

对于所有的数据,1≤BPi≤APi≤1000,1≤ASi,BSi≤MaxP


code

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
int T,Maxp,w,ap,bp,as,bs,head,tail,p[2005],f[2005][2005];
int main()
{
    cin>>T>>Maxp>>w;
    memset(f,128,sizeof(f)); 
    for(int i=1;i<=T;i++)
	{
        cin>>ap>>bp>>as>>bs;
        for(int j=0;j<=as;j++)f[i][j]=-1*j*ap;
        for(int j=0;j<=Maxp;j++)f[i][j]=max(f[i][j],f[i-1][j]);
        if(i<=w)continue;
        head=1;
        tail=0;
        for(int j=0;j<=Maxp;j++)
		{
			while(f[i-w-1][p[tail]]+p[tail]*ap<=f[i-w-1][j]+j*ap&&head<=tail)tail--;
            p[++tail]=j; 
			while(p[head]<j-as&&head<=tail)head++; 
            if(head<=tail)f[i][j]=max(f[i][j],f[i-w-1][p[head]]+p[head]*ap-j*ap);
        }
        head=1;
        tail=0;
        for(int j=Maxp;j>=0;j--)
		{
            while(f[i-w-1][p[tail]]+p[tail]*bp<=f[i-w-1][j]+j*bp&&head<=tail)tail--;
            p[++tail]=j;
			while(p[head]>j+bs&&head<=tail)head++;
            if(head<=tail)f[i][j]=max(f[i][j],f[i-w-1][p[head]]+p[head]*bp-j*bp);
        }
    }
    int s=0;
    for(int i=0;i<=Maxp;i++)
     s=max(s,f[T][i]);
    cout<<s; 
}


posted @ 2020-08-11 21:34  unknown_future  阅读(57)  评论(0编辑  收藏  举报