【题解】 量化交易4

题目描述

【题目描述】
  applepi训练了一个可以自动在股票市场进行量化交易的模型。
  通常来说,applepi写出的模型,你懂得,就好比一架印钞机。不过为了谨慎起见,applepi还是想先检查一下模型的效果。
  applpie收集了“塞帕思股份(surpass)”在最近的连续N天内的价格。在每一天中,他可以做如下事情之一:
    1. 睡(把)觉(妹)。
    2. 以当天的价格作为成交价买入1股“塞帕思”的股票。
    3. 以当天的价格作为成交价卖出1股“塞帕思”的股票。
  最初applepi不持有该股票。现在你需要计算出在最优策略下,N天后applepi能够获得的最大利润。
  为了维护森林的和平,本着清仓甩锅的原则,在N天的交易结束后applepi也不能持有“塞帕思”的股票。
  此外,为了防止垄断,市场管理部门规定,如果applepi手中已经持有股票,那么他当前就不能再购买股票。
  换句话说,applepi手中最多只能持有1股“塞帕思”的股票。
  同时为了检验方便,applepi最多只会进行k次交易,也就说applepi最多只会买k次,卖k次。
【输入格式】
  每个测试点包含若干组数据,以EOF结尾。对于每组数据:
  第一行1个整数N。
  第二行N个正整数,相邻两个整数之间用1个空格隔开,表示每一天股票的价格。
【输出格式】
  对于每组数据,首先按样例所示的格式“Case #k:”输出该组数据的编号,然后输出一个整数,表示applepi最大能够获得的利润。
【样例】
  样例输入1
    3 2
    2 4 1
  样例输出1
    2
  样例输入2
    6 2
    3 2 6 5 0 3
  样例输出2
    7
【数据规模与约定】
  对于50%的数据,1≤N≤1000。
  对于100%的数据,1≤N≤100000,股票价格不超过100000,每个测试点至多包含5组数据。

思路

这道题与量化交易2极其相似,只多了一个买卖次数的限制。那么,就可以参考 【题解】 量化交易2 的方法,用DP解决。
首先,在阶段性上,这道题与量化交易2并无区别。
然后,状态定义上就要新增一维表示买卖次数,即 \(dp{i,j,0}\) 表示 前 \(i\) 天买卖 \(j\) 次过后,手上没有股票的最大利润;\(dp{i,j,1}\) 表示 前 \(i\) 天买卖 \(j\) 次过后,手上有股票的最大利润。
接着,状态转移方程就要根据状态一起增加一维的转移,即 $$dp_{i,j,0} = \max(dp_{i-1,j,0}, dp_{i-1,j-1,1}+a_i), j > 0$$ $$dp_{i,j,1} = \max(dp_{i-1,j,1}, dp_{i-1,j,0}-a_i)$$
其中 \(1 \le i \le n, 0 \le j \le k\)
最后定义初值:\(dp = -\infty, dp_{0,0,0} = 0\)
以及,因为题目只是要求最大买卖 \(k\) 次,但是买卖次数可以不足 \(k\) 次,所以最终的目标利润为:\(\max_{1 \le i \le k} (dp_{n,i,0})\)
还有一个细节问题,如果以题目的数据规模,定义dp数组用静态定义会爆内存,所以要使用动态定义。

代码

#include <bits/stdc++.h>
using namespace std;

const int N = 1e5 + 5;
int n, k, a[N];

int main()
{
    scanf("%d%d", &n, &k);
    for (int i = 1; i <= n; i ++ ) scanf("%d", &a[i]);

    int dp[n + 5][k + 5][3]; // 动态定义
    memset(dp, 128, sizeof dp);
    dp[0][0][0] = 0;
    for (int i = 1; i <= n; i ++ )
        for (int j = 0; j <= k; j ++ )
        {
            dp[i][j][0] = dp[i - 1][j][0];
            if (j) dp[i][j][0] = max(dp[i][j][0], dp[i - 1][j - 1][1] + a[i]);
            dp[i][j][1] = max(dp[i - 1][j][1], dp[i - 1][j][0] - a[i]);
        }
    int ans = INT_MIN;
    for (int i = 0; i <= k; i ++ ) ans = max(ans, dp[n][i][0]);
    printf("%d\n", ans);

    return 0;
}
posted @ 2024-04-30 19:33  T_泓  阅读(27)  评论(0编辑  收藏  举报