【八月刷题打卡】股票交易

182 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第30天,点击查看活动详情

[SCOI2010]股票交易

题目描述

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

通过一段时间的观察,lxhgww\text{lxhgww} 预测到了未来 TT 天内某只股票的走势,第 ii 天的股票买入价为每股 APiAP_i,第 ii 天的股票卖出价为每股 BPiBP_i(数据保证对于每个 ii,都有 APiBPiAP_i \geq BP_i),但是每天不能无限制地交易,于是股票交易所规定第 ii 天的一次买入至多只能购买 ASiAS_i 股,一次卖出至多只能卖出 BSiBS_i 股。

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

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

输入格式

输入数据第一行包括 33 个整数,分别是 TTMaxP\text{MaxP}WW

接下来 TT 行,第 ii 行代表第 i1i-1 天的股票走势,每行 44 个整数,分别表示 APi, BPi, ASi, BSiAP_i,\ BP_i,\ AS_i,\ BS_i

输出格式

输出数据为一行,包括 11 个数字,表示 lxhgww\text{lxhgww} 能赚到的最多的钱数。

样例 #1

样例输入 #1

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

样例输出 #1

3

提示

对于 30%30\% 的数据,0W<T50,1MaxP500\leq W<T\leq 50,1\leq\text{MaxP}\leq50

对于 50%50\% 的数据,0W<T2000,1MaxP500\leq W<T\leq 2000,1\leq\text{MaxP}\leq50

对于 100%100\% 的数据,0W<T2000,1MaxP20000\leq W<T\leq 2000,1\leq\text{MaxP}\leq2000

对于所有的数据,1BPiAPi1000,1ASi,BSiMaxP1\leq BP_i\leq AP_i\leq 1000,1\leq AS_i,BS_i\leq\text{MaxP}

#include <cstdio>
#include <algorithm>
using namespace std;

const int INF=2000000000;
int t,maxp,w,ap[2010],bp[2010],as[2010],bs[2010],d[2010][2010],q[2010],p[2010],head,tail;

inline int read(){
    int num=0,k=1; char c=getchar();
    while(c>'9' || c<'0') k=(c=='-')?0:k,c=getchar();
    while(c>='0' && c<='9') num=num*10+c-'0',c=getchar();
    return k?num:-num;
}

int main(){
    t=read(); maxp=read(); w=read();
    for(int i=1;i<=maxp;i++) d[0][i]=-INF;
    for(int i=1;i<=t;i++) ap[i]=read(),bp[i]=read(),as[i]=read(),bs[i]=read();
    for(int cur=1,las;cur<=t;cur++){
        las=max(0,cur-w-1);
        for(int i=0;i<=maxp;i++) d[cur][i]=d[cur-1][i];
        head=1; tail=0;
        for(int i=0;i<=maxp;i++){
            while(head<=tail && q[tail]<=d[las][i]+i*ap[cur]) tail--;
            q[++tail]=d[las][i]+i*ap[cur]; p[tail]=i;
            while(head<=tail && i-p[head]>as[cur]) head++;
            d[cur][i]=max(d[cur][i],q[head]-i*ap[cur]);
        }
        head=1; tail=0;
        for(int i=maxp;i>=0;i--){
            while(head<=tail && q[tail]<=d[las][i]+i*bp[cur]) tail--;
            q[++tail]=d[las][i]+i*bp[cur]; p[tail]=i;
            while(head<=tail && p[head]-i>bs[cur]) head++;
            d[cur][i]=max(d[cur][i],q[head]-i*bp[cur]);
        }
    }
    printf("%d",d[t][0]);
    return 0;
}