洛谷傳送門
BZOJ傳送門
題目描述
最近 又迷上了投資股票,通過一段時間的觀察和學習,他總結出了股票行情的一些規律。
通過一段時間的觀察, 預測到了未來 天內某隻股票的走勢,第 天的股票買入價爲每股 ,第 天的股票賣出價爲每股 (數據保證對於每個 ,都有 ),但是每天不能無限制地交易,於是股票交易所規定第 天的一次買入至多隻能購買 股,一次賣出至多隻能賣出 股。
另外,股票交易所還制定了兩個規定。爲了避免大家瘋狂交易,股票交易所規定在兩次交易(某一天的買入或者賣出均算是一次交易)之間,至少要間隔 天,也就是說如果在第 天發生了交易,那麼從第 天到第 天,均不能發生交易。同時,爲了避免壟斷,股票交易所還規定在任何時間,一個人的手裏的股票數不能超過 。
在第 天之前, 手裏有一大筆錢(可以認爲錢的數目無限),但是沒有任何股票,當然, 天以後, 想要賺到最多的錢,聰明的程序員們,你們能幫助他嗎?
輸入輸出格式
輸入格式:
輸入數據第一行包括 個整數,分別是 ,,。
接下來 行,第 $i $行代表第 天的股票走勢,每行 個整數,分別表示 。
輸出格式:
輸出數據爲一行,包括 個數字,表示 能賺到的最多的錢數。
輸入輸出樣例
輸入樣例#1:
5 2 0
2 1 1 1
2 1 1 1
3 2 1 1
4 3 1 1
5 4 1 1
輸出樣例#1:
3
說明
對於 的數據,
對於 的數據,
對於 的數據,
對於所有的數據,
解題分析
設表示第天手上還有張股票能賺到的最大值。 那麼有如下轉移:
-
這一天啥都不幹:
-
這一天在沒有票的基礎上買了一些票:
-
這一天在第天的基礎上賣了一些票:
取值範圍是個滑動窗口, 單調隊列優化。 -
這一天在第天的基礎上買了一些票: 和上面的式子差不多。
所以兩個單調隊列就好了。 總複雜度。
代碼如下:
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <algorithm>
#define R register
#define IN inline
#define MX 2005
#define W while
#define gc getchar()
#define ll long long
template <class T>
IN void in(T &x)
{
x = 0; R char c = gc;
for (; !isdigit(c); c = gc);
for (; isdigit(c); c = gc)
x = (x << 1) + (x << 3) + c - 48;
}
template <class T> IN T max(T a, T b) {return a > b ? a : b;}
template <class T> IN T min(T a, T b) {return a < b ? a : b;}
int dp[MX][MX];
int T, UP, halt, h, t;
int cost[MX], val[MX], lin[MX], lout[MX], que[MX];
int main(void)
{
in(T), in(UP), in(halt);
for (R int i = 1; i <= T; ++i)
in(cost[i]), in(val[i]), in(lin[i]), in(lout[i]);
std::memset(dp, 128, sizeof(dp));
for (R int i = 1; i <= T; ++i)
{
for (R int j = 0; j <= lin[i]; ++j) dp[i][j] = max(dp[i - 1][j], -cost[i] * j);
for (R int j = lin[i] + 1; j <= UP; ++j) dp[i][j] = dp[i - 1][j];
if (i > halt + 1)
{
int tar = i - halt - 1;
que[h = t = 0] = 0;
for (R int j = 1; j <= UP; ++j)
{
W (h < t && que[h] < j - lin[i]) ++h;
if (h <= t)
dp[i][j] = max(dp[i][j], dp[tar][que[h]] - (j - que[h]) * cost[i]);
W (h <= t && dp[tar][que[t]] + que[t] * cost[i] < dp[tar][j] + j * cost[i]) --t;
que[++t] = j;
}
que[h = t = 0] = UP;
for (R int j = UP - 1; ~j; --j)
{
W (h < t && que[h] > j + lout[i]) ++h;
if (h <= t)
dp[i][j] = max(dp[i][j], dp[tar][que[h]] + (que[h] - j) * val[i]);
W (h <= t && dp[tar][que[t]] + que[t] * val[i] < dp[tar][j] + j * val[i]) --t;
que[++t] = j;
}
}
}
printf("%d\n", dp[T][0]);
}