【ACWing】1058. 股票买卖 V

题目地址:

https://www.acwing.com/problem/content/1060/

给定一个长度为 N N N的数组,数组中的第 i i i个数字表示一个给定股票在第 i i i天的价格。设计一个算法计算出最大利润。在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股票):你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。卖出股票后,你无法在第二天买入股票(即冷冻期为 1 1 1天)。

输入格式:
第一行包含整数 N N N,表示数组长度。第二行包含 N N N个不超过 10000 10000 10000的正整数,表示完整的数组。

输出格式:
输出一个整数,表示最大利润。

数据范围:
1 ≤ N ≤ 1 0 5 1≤N≤10^5 1N105

思路是动态规划,可以用状态机来模拟整个过程,设三个状态,分别是持有、卖出和冷冻。设 f [ i ] [ 0 , 1 , 2 ] f[i][0,1,2] f[i][0,1,2]分别代表第 i i i天结束时的三个状态下的最大利润,并且设第 i i i天股价是 p [ i ] p[i] p[i],则有:
1、今天持有可以由昨天持有、昨天冷冻转移而来,则有 f [ i ] [ 0 ] = max ⁡ { f [ i − 1 ] [ 0 ] , f [ i − 1 ] [ 2 ] − p [ i ] } f[i][0]=\max\{f[i-1][0],f[i-1][2]-p[i]\} f[i][0]=max{ f[i1][0],f[i1][2]p[i]}
2、今天卖出可以由昨天持有转移而来,所以 f [ i ] [ 1 ] = f [ i − 1 ] [ 0 ] + p [ i ] f[i][1]=f[i-1][0]+p[i] f[i][1]=f[i1][0]+p[i]
3、今天冷冻可以由昨天冷冻或者昨天卖出转移而来,所以 f [ i ] [ 2 ] = max ⁡ { f [ i − 1 ] [ 2 ] , f [ i − 1 ] [ 1 ] } f[i][2]=\max\{f[i-1][2],f[i-1][1]\} f[i][2]=max{ f[i1][2],f[i1][1]}
最后返回 max ⁡ { f [ n ] [ 1 ] , f [ n ] [ 2 ] } \max\{f[n][1],f[n][2]\} max{ f[n][1],f[n][2]}。代码如下:

#include <iostream>
using namespace std;

const int N = 1e5 + 10;
int n;
int a[N], hold[N], sell[N], cool[N];

int main() {
    
    
    cin >> n;
    for (int i = 1; i <= n; i++) {
    
    
        cin >> a[i];
    }

    hold[0] = sell[0] = -1e9;
    for (int i = 1; i <= n; i++) {
    
    
        hold[i] = max(hold[i - 1], cool[i - 1] - a[i]);
        sell[i] = hold[i - 1] + a[i];
        cool[i] = max(cool[i - 1], sell[i - 1]);
    }

    cout << max(sell[n], cool[n]) << endl;

    return 0;
}

时空复杂度 O ( N ) O(N) O(N)

猜你喜欢

转载自blog.csdn.net/qq_46105170/article/details/114427343
今日推荐