嘘~ 正在从服务器偷取页面 . . .

洛谷P2569 [SCOI2010] 股票交易 题解


洛谷P2569 [SCOI2010] 股票交易 题解

题目链接:P2569 [SCOI2010] 股票交易

题意

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

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

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

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

输入格式

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

接下来 $T$ 行,第 $i$ 行代表第 $i-1$ 天的股票走势,每行 $4$ 个整数,分别表示 $AP_i,\ BP_i,\ AS_i,\ BS_i$。

输出格式

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

数据范围

$0\leq W<T\leq 2000,1\leq\text{MaxP}\leq 2000,1\leq BP_i\leq AP_i\leq 1000,1\leq AS_i,BS_i\leq\text{MaxP}$。

设 $f(i,j)$ 为前 $i$ 天,手上有 $j$ 股股票的最大收益。

初值是 $f(i,j)=-\infty$ 。考虑转移。

  1. $i$ 是第一次买,有
  1. 不买也不卖,有
  1. 买,从 $f(i-w-1,\,k)$ 转移一定不劣,那么

  2. 卖,同理,有

显然可以单调队列优化。

时间复杂度 $\mathcal{O}(n)$

代码:

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define INF 0x3f3f3f3f3f3f3f3f
void up(int &x, int y) { x < y ? x = y : 0; }
void down(int &x, int y) { x > y ? x = y : 0; }
#define rep(i, a, b) for(int i = (a), i##END = (b); i <= i##END; i++)
#define Rep(i, a, b) for(int i = (a), i##END = (b); i >= i##END; i--)
#define N ((int)(2e3 + 15))

int st, en, q[N], f[N][N];
signed main()
{
    ios::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);
    // freopen("check.in","r",stdin);
    // freopen("check.out","w",stdout);
    int n, m, w; cin >> n >> m >> w;
    memset(f, 0xc0, sizeof(f));
    rep(i, 1, n)
    {
        static int ap, bp, as, bs; cin >> ap >> bp >> as >> bs;
        rep(j, 0, as) f[i][j] = -1 * j * ap;
        rep(j, 0, m) up(f[i][j], f[i - 1][j]);
        if(i <= w) continue; st = en = 0; 
        rep(j, 0, m)
        {
            while(st < en && q[st + 1] < j - as) ++st;
            while(st < en && f[i - w - 1][q[en]] + q[en] * ap <= f[i - w - 1][j] + j * ap) --en;
            q[++en] = j;
            if(st < en) up(f[i][j], f[i - w - 1][q[st + 1]] + q[st + 1] * ap - j * ap);
        }
        st = en = 0;
        Rep(j, m, 0)
        {
            while(st < en && q[st + 1] > j + bs) ++st;
            while(st < en && f[i - w - 1][q[en]] + q[en] * bp <= f[i - w - 1][j] + j * bp) --en;
            q[++en] = j;
            if(st < en) up(f[i][j], f[i - w - 1][q[st + 1]] + q[st + 1] * bp - j * bp);
        }
    }
    int res = 0; rep(i, 0, m) up(res, f[n][i]);
    cout << res << '\n';
    return 0;
}

参考文献

[1] https://www.cnblogs.com/Plozia/p/16731981.html


文章作者: q779
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-ND 4.0 许可协议。转载请注明来源 q779 !
评论
  目录