#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 100010;
const int K = 110;
int a[N];
int f[N][K];
int main()
{
int n, k;
cin >> n >> k;
for (int i = 1; i <= n; i++)cin >> a[i];
int res = 0;
for (int j = 1; j <= k; j++) {
int max1=f[1][j],max2=f[0][j-1]-a[1];
for (int i = 2; i <= n; i++) {
max1 = max(max1, f[i - 1][j]);
max2 = max(max2, f[i-2][j-1]-a[i-1]);
f[i][j] = max(max1, max2+a[i]);
res = max(res, f[i][j]);
}
}
cout << res << endl;
return 0;
}
二维状态表示,望采纳
首先,因为这个问题可以定义每一天买或者不买,所以我们不能定义前i天完成j个交易的利润最大值,这样不知道最后一次是那一天卖出的,也就计算不了下一次获得的利润是多少。所以我们定义f[i][j]为第i天完成j笔交易获得的最大值。
之后我们分析怎么计算:
有了之前的经验,我们也把这个计算分为两个部分。
第一个部分是第i天卖出,那么就会增加相应的利润。
第二个部分是第i天买入或者不做动作,那么这个状态的利润不会增加。
具体计算方式如下:
可以看到,分为的两个部分最大值分别为max1,max2。
因为我们需要在j不变的情况下找i变化的利润最大值,所以我们需要先遍历j再遍历i。在j不变的情况下每次比较新增的一项即可找到每次的最大值。
初始化:
max1代表前i-1天完成j笔交易的最大值,初始化为f[1][j]。
max2代表第k天完成j-1笔交易减去第k+1天的利润的最大值,这个值加上第i天的利润就是最后计算得到的利润。(看上述图片,可以发现max2计算的时候,都会加上a[i],这是个常量,所以我们只用计算除去a[i],其余变量的最大值,这个就是max2的含义)初始化为f[0][j-1]-a[1]。
之后遍历即可,注意我们至少从第二天才会完成第一笔交易,所以i从2开始遍历,j从1遍历即可