cf F1. Stock Trading (dp)

F1. Stock Trading
time limit per test
3 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

This problem consists of three subproblems: for solving subproblem F1 you will receive 8 points, for solving subproblem F2 you will receive 15 points, and for solving subproblem F3 you will receive 10 points.

Manao has developed a model to predict the stock price of a company over the next n days and wants to design a profit-maximizing trading algorithm to make use of these predictions. Unfortunately, Manao's trading account has the following restrictions: 

  • It only allows owning either zero or one shares of stock at a time; 
  • It only allows buying or selling a share of this stock once per day; 
  • It allows a maximum of k buy orders over the next n days; 

For the purposes of this problem, we define a trade to a be the act of buying one share of stock on day i, then holding the stock until some day j > i at which point the share is sold. To restate the above constraints, Manao is permitted to make at most k non-overlapping trades during the course of an n-day trading period for which Manao's model has predictions about the stock price.

Even though these restrictions limit the amount of profit Manao can make compared to what would be achievable with an unlimited number of trades or the ability to hold more than one share at a time, Manao still has the potential to make a lot of money because Manao's model perfectly predicts the daily price of the stock. For example, using this model, Manao could wait until the price is low, then buy one share and hold until the price reaches a high value, then sell for a profit, and repeat this process up to k times until n days have passed.

Nevertheless, Manao is not satisfied by having a merely good trading algorithm, and wants to develop an optimal strategy for trading subject to these constraints. Help Manao achieve this goal by writing a program that will determine when to buy and sell stock to achieve the greatest possible profit during the n-day trading period subject to the above constraints.

Input

The first line contains two integers n and k, separated by a single space, with . The i-th of the following n lines contains a single integer pi (0 ≤ pi ≤ 1012), where pi represents the price at which someone can either buy or sell one share of stock on day i.

The problem consists of three subproblems. The subproblems have different constraints on the input. You will get some score for the correct submission of the subproblem. The description of the subproblems follows.

  • In subproblem F1 (8 points), n will be between 1 and 3000, inclusive. 
  • In subproblem F2 (15 points), n will be between 1 and 100000, inclusive. 
  • In subproblem F3 (10 points), n will be between 1 and 4000000, inclusive. 
Output

For this problem, the program will only report the amount of the optimal profit, rather than a list of trades that can achieve this profit.

Therefore, the program should print one line containing a single integer, the maximum profit Manao can achieve over the next n days with the constraints of starting with no shares on the first day of trading, always owning either zero or one shares of stock, and buying at most k shares over the course of the n-day trading period.

Examples
input
Copy
10 2
2
7
3
9
8
7
9
7
1
9
output
Copy
15
input
Copy
10 5
2
7
3
9
8
7
9
7
1
9
output
Copy
21
Note

In the first example, the best trade overall is to buy at a price of 1 on day 9 and sell at a price of 9 on day 10 and the second best trade overall is to buy at a price of 2 on day 1 and sell at a price of 9 on day 4. Since these two trades do not overlap, both can be made and the profit is the sum of the profits of the two trades. Thus the trade strategy looks like this: 

2    | 7    | 3    | 9    | 8    | 7    | 9    | 7    | 1    | 9
buy  |      |      | sell |      |      |      |      | buy  | sell

The total profit is then (9 - 2) + (9 - 1) = 15.

In the second example, even though Manao is allowed up to 5 trades there are only 4 profitable trades available. Making a fifth trade would cost Manao money so he only makes the following 4: 

2    | 7    | 3    | 9    | 8    | 7    | 9    | 7    | 1    | 9
buy  | sell | buy  | sell |      | buy  | sell |      | buy  | sell

The total profit is then (7 - 2) + (9 - 3) + (9 - 7) + (9 - 1) = 21.


很经典的dp问题

建立dp[i][j] 表示对前j支股票 进行i次交易

对于求第i次交易的最大值,我们需要知道第i - 1次的最大值。因为我们需要收益最大,所以我们尽量买入的时候尽量花钱少。

所以设 _max = max(dp[i - 1][j - 1] - a[j], _max);     dp[i - 1][j - 1]是前j - 1只股票进行i - 1次交易的最大值

另然后买入第j支股票剩下的钱最多即_max

然后dp[i][j] = max(dp[i][j - 1], _max + a[j])。 求卖出后的最大值


然后我们发现第i次交易只与第i - 1次交易有关,所以我们可以采用滚动数组的方法,来节约空间

#include <iostream>
#include <algorithm>
#include <map>
#include <cmath>
#include <string.h>
#include <utility>
#include <unordered_map>
using namespace std;
using ll = long long;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int maxn = 1000100;
ll dp[2][maxn];
ll a[maxn];
int rf(int flag) {
    return 1 - flag;
}
void cf(int& flag) {
    flag = 1 - flag;
}
int main() {
    //freopen("in.txt", "r", stdin);
    int n, k;
    cin >> n >> k;
    for (int i = 1; i <= n; ++i) {
        cin >> a[i];
    }
    int flag = 0;
    for (int i = 1; i <= k; ++i) {
        cf(flag);
        ll _max = -INF;
        for (int j = 1; j <= n; ++j) {
            _max = max(_max, dp[rf(flag)][j - 1] - a[j]);
            dp[flag][j] = max(dp[flag][j - 1], _max + a[j]);
        }
    }
    cout << dp[flag][n] << endl;
    
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值