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

洛谷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\) 是第一次买,有 \[ f(i,j) = -j\times \mathrm{ap}_i \]

  2. 不买也不卖,有 \[ f(i,j) \uparrow f(i-1,j) \]

  3. 买,从 \(f(i-w-1,\,k)\) 转移一定不劣,那么 \[ f(i,j) \uparrow \max_{j - \mathrm{as}_i \le k \le j}\{f(i-w-1,\,k) - (j - k)\times \mathrm{ap}_i\} \]

  4. 卖,同理,有 \[ f(i,j) \uparrow \max_{j \le k \le j + \mathrm{bs}_i}\{f(i-w-1,\,k) + (k - j)\times \mathrm{bp}_i\} \]

显然可以单调队列优化。

时间复杂度 \(\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 !
评论
  目录