题目描述

给定一个长度为 \(N\) 的数组,数组中的第 \(i\) 个数字表示一个给定股票在第 \(i\) 天的价格。

设计一个算法计算出最大利润。在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股票):

你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。

卖出股票后,你无法在第二天买入股票 (即冷冻期为 \(1\) 天)。

输入格式

第一行包含整数 \(N\),表示数组长度。

第二行包含 \(N\) 个不超过 \(10000\) 的正整数,表示完整的数组。

输出格式

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

数据范围

\(1 \leq N \leq 105\)



 所不同,这题没有买卖股票次数的限制,所以我们并不需要另开一维来存交易了多少次。

那我们有\(dp[i][0, 1]\)表示考虑\(i\)天,这时手里有股票(1)还是没有股票(0)的最大利润。

先看\(dp[i][0]\),这时手里没有股票,那么他有可能从两种情况转移来:

  1. 本来我有股票,但是我卖了,然后得到了\(w[i]\)的利润,那么这个状态是: \(dp[i - 1][1] + w[i]\)。
  2. 本来我就没有股票,这次也没买,那么这个状态是: \(dp[i - 1][0]\)。

然后从上面两种情况找最大值。

所以\(dp[i][0] = max(dp[i - 1][1] + w[i], dp[i - 1][0])\)



再看\(dp[i][1]\),这时手里有股票,那么他也有可能从两种情况转移来:

  1. 我手里没有股票,并且我昨天没有卖股票也没有买股票,今天买了,而且花了\(w[i]\)的钱,那么这个状态是: \(dp[i - 2][0] - w[i]\)。
  2. 本来我就有股票,这次也没卖,那么这个状态是: \(dp[i - 1][1]\)。

然后从上面两种情况找最大值。

所以\(dp[i][1] = max(dp[i - 2][0] - w[i], dp[i - 1][1])\)

初始值,\(dp[i][0] = 0\) 这不显然

#include <bits/stdc++.h>
using namespace std;
#define MAXN 100005
int w[MAXN], dp[MAXN][2];
int main()
{
int n;
scanf("%d", &n);
for(int i = 1; i <= n; i++)
scanf("%d", &w[i]);
memset(dp, -0x3f, sizeof(dp));
for(int i = 0; i <= n; i++)
dp[i][0] = 0;
for(int i = 1; i <= n; i++)
{
dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] + w[i]);
dp[i][1] = max(dp[i - 1][1], dp[i - 2][0] - w[i]);
}
printf("%d\n", dp[n][0]);
return 0;
}