设f[i][j]f[i][j]表示到了第ii天,手里有张股票,赚到最多的钱。
如果第ii天不进行交易,则可以从f[i−1][j]f[i−1][j]转移。即:
f[i][j]=f[i−1][j]f[i][j]=f[i−1][j]
如果第ii天进行交易,则可以从f[max(0,i−W−1)][...]f[max(0,i−W−1)][...]转移。
(下面设p=max(0,i−W−1)p=max(0,i−W−1))
设存在非负整数k,hk,h满足k>hk>h,
判断h×BPi−k×APih×BPi−k×APi和−(k−h)×APi−(k−h)×APi的大小关系。
把右边拆开得到h×APi−k×APih×APi−k×APi,由于APi≥BPiAPi≥BPi且h>0h>0,
因此−(k−h)×APi≥h×BPi−k×APi−(k−h)×APi≥h×BPi−k×APi。
k<hk<h时同理。因此得出:在最优情况下,一天要么不进行交易,要么只买入,要么只卖出。
所以得出第ii天进行交易时的转移:
f[i][j]=max(f[i][j],maxj<k≤BSi+j{f[p][k]+(k−j)×BPi})f[i][j]=max(f[i][j],maxj<k≤BSi+j{f[p][k]+(k−j)×BPi})
将等号右边maxmax里的式子拆开,得到:
maxj−ASi≤k<j{f[p][k]+k×APi}−j×APimaxj−ASi≤k<j{f[p][k]+k×APi}−j×APi
maxj<k≤BSi+j{f[p][k]+k×BPi}−j×BPimaxj<k≤BSi+j{f[p][k]+k×BPi}−j×BPi
复杂度O(T×MaxP2)O(T×MaxP2)
考虑到j−ASij−ASi和BSi+jBSi+j随jj单调递增,
因此可以用单调队列分别维护和f[p][k]+k×BPif[p][k]+k×BPi的最大值。复杂度O(T×MaxP)O(T×MaxP)。
代码:
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
inline int read() {
int res = 0; bool bo = 0; char c;
while (((c = getchar()) < '0' || c > '9') && c != '-');
if (c == '-') bo = 1; else res = c - 48;
while ((c = getchar()) >= '0' && c <= '9')
res = (res << 3) + (res << 1) + (c - 48);
return bo ? ~res + 1 : res;
}
const int N = 2005, INF = 0x3f3f3f3f;
int T, maxP, W, AP[N], BP[N], AS[N], BS[N], f[N][N], He, Ta, Q[N];
bool ex[N][N];
int main() {
int i, j; T = read(); maxP = read(); W = read();
for (i = 1; i <= T; i++) AP[i] = read(), BP[i] = read(),
AS[i] = read(), BS[i] = read(); ex[0][0] = 1;
for (i = 1; i <= T; i++) {
for (j = 0; j <= maxP; j++) f[i][j] = -INF;
for (j = 0; j <= maxP; j++) if (ex[i - 1][j])
f[i][j] = f[i - 1][j], ex[i][j] = 1; int p = max(0, i - W - 1);
He = Ta = 0; for (j = 0; j <= maxP; j++) {
while (He < Ta && j - Q[He + 1] > AS[i]) He++;
if (He != Ta) f[i][j] = max(f[i][j], f[p][Q[He + 1]]
- (j - Q[He + 1]) * AP[i]), ex[i][j] = 1;
if (ex[p][j]) {
while (He < Ta && f[p][Q[Ta]] + Q[Ta] * AP[i] <
f[p][j] + j * AP[i]) Ta--; Q[++Ta] = j;
}
}
He = Ta = 0; for (j = maxP; j >= 0; j--) {
while (He < Ta && Q[He + 1] - j > BS[i]) He++;
if (He != Ta) f[i][j] = max(f[i][j], f[p][Q[He + 1]]
+ (Q[He + 1] - j) * BP[i]), ex[i][j] = 1;
if (ex[p][j]) {
while (He < Ta && f[p][Q[Ta]] + Q[Ta] * BP[i] <
f[p][j] + j * BP[i]) Ta--; Q[++Ta] = j;
}
}
}
int ans = -INF; for (i = 0; i <= maxP; i++)
if (ex[T][i]) ans = max(ans, f[T][i]); cout << ans << endl;
return 0;
}