买卖股票问题

能否当天买入当天卖出

有时候题目规定,不可以当天买入当天卖出。但我们一般情况下不必考虑这个,只需要将 \(res\) 初始化为 \(0\),确保利润不可能为负数即可。

1. 只能买卖一次

贪心选择买入时机,枚举卖出时机。

2. 可以买卖无限次

线性 \(DP\)\(f[i][j]\)
\(j=0\) :在第 \(i\) 天买入时的最大利润
\(j=1\) :在第 \(i\) 天卖出时的最大利润

3. 含手续费

每次卖出时额外减去手续费即可。

4. 含冷冻期

线性 \(DP\):买入时,必须通过前一天的卖出来转移。

5. 最多买卖 \(k\)

线性 \(DP\)\(f[i][j][k]\)
\(f[i][j][0]\):在第 \(i\) 天,第 \(j\) 次交易,买入时的最大利润
\(f[i][j][1]\):在第 \(i\) 天,第 \(j\) 次交易,卖出时的最大利润
另外就是注意初始化问题,这里的初始化比较复杂?

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 1e5 + 10, M = 110, INF = 0x3f3f3f3f;

int n, k, w[N];
// f[i][j][0]:在第i天,第j次交易,买入时的最大利润
// f[i][j][1]:在第i天,第j次交易,卖出时的最大利润
int f[2][M][2]; // 滚动数组优化

int main()
{
    cin >> n >> k;
    for(int i = 1; i <= n; i ++ )   cin >> w[i];
    
    // 这里的初始化主要是处理i=0以及j=0的情况
    // 由于我们求的是最大值,因此这里要初始化为最小值
      // (1)对于卖出的情况,我们可以当天买入当天卖出,因此最大利润至少为0
      // (2)对于买入的情况,由于第0天不存在,买入不合法,因此我们应该将其初始化为最小值
        // 不过特殊的,对于j=0时,交易不存在,可以理解为既没有买入也没有卖出,此时最大利润应该为0
    for(int i = 1; i <= k; i ++ )   f[0][i][0] = -INF;

    int res = 0;
    for(int i = 1; i <= n; i ++ )
    {
        for(int j = 1; j <= k; j ++ )
        {
            // 0: 买入股票
            f[i & 1][j][0] = max(
                // 上一次就持有股票 or 这一次购入
                f[(i - 1) & 1][j][0], f[(i - 1) & 1][j - 1][1] - w[i]
            );
            // 1:卖出股票
            f[i & 1][j][1] = max(
                // 上一次就未持有股票 or 这次卖了
                f[(i - 1) & 1][j][1], f[(i - 1) & 1][j][0] + w[i]
            );
            res = max(res, f[i & 1][j][1]);
        }
    }
    cout << res << endl;
    
    return 0;
}
posted @ 2024-11-06 17:04  光風霽月  阅读(3)  评论(0编辑  收藏  举报