[Luogu P2569] [BZOJ 1855] [SCOI2010]股票交易

洛谷傳送門

BZOJ傳送門

題目描述

最近 lxhgww\text{lxhgww} 又迷上了投資股票,通過一段時間的觀察和學習,他總結出了股票行情的一些規律。

通過一段時間的觀察,lxhgww\text{lxhgww} 預測到了未來 TT 天內某隻股票的走勢,第 ii 天的股票買入價爲每股 APiAP_i,第 ii天的股票賣出價爲每股 BPiBP_i(數據保證對於每個 ii,都有 APiBPiAP_i \geq BP_i),但是每天不能無限制地交易,於是股票交易所規定第 ii 天的一次買入至多隻能購買 ASiAS_i 股,一次賣出至多隻能賣出 BSiBS_i 股。

另外,股票交易所還制定了兩個規定。爲了避免大家瘋狂交易,股票交易所規定在兩次交易(某一天的買入或者賣出均算是一次交易)之間,至少要間隔 WW 天,也就是說如果在第 ii 天發生了交易,那麼從第 i+1i+1 天到第 i+Wi+W 天,均不能發生交易。同時,爲了避免壟斷,股票交易所還規定在任何時間,一個人的手裏的股票數不能超過 MaxP\text{MaxP}

在第 11 天之前,lxhgww\text{lxhgww} 手裏有一大筆錢(可以認爲錢的數目無限),但是沒有任何股票,當然,TT 天以後,lxhgww\text{lxhgww} 想要賺到最多的錢,聰明的程序員們,你們能幫助他嗎?

輸入輸出格式

輸入格式:

輸入數據第一行包括 33 個整數,分別是 TTMaxP\text{MaxP}WW

接下來 TT 行,第 $i $行代表第 i1i-1 天的股票走勢,每行 44 個整數,分別表示 APi, BPi, ASi, BSiAP_i,\ BP_i,\ AS_i,\ BS_i

輸出格式:

輸出數據爲一行,包括 11 個數字,表示 lxhgww\text{lxhgww} 能賺到的最多的錢數。

輸入輸出樣例

輸入樣例#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

說明

對於 30%30\% 的數據,0W<T50,1MaxP500\leq W<T\leq 50,1\leq\text{MaxP}\leq50

對於 50%50\% 的數據,0W<T2000,1MaxP500\leq W<T\leq 2000,1\leq\text{MaxP}\leq50

對於 100%100\% 的數據,0W<T2000,1MaxP20000\leq W<T\leq 2000,1\leq\text{MaxP}\leq2000

對於所有的數據,1BPiAPi1000,1ASi,BSiMaxP1\leq BP_i\leq AP_i\leq 1000,1\leq AS_i,BS_i\leq\text{MaxP}

解題分析

dp[i][j]dp[i][j]表示第ii天手上還有jj張股票能賺到的最大值。 那麼有如下轉移:

  1. 這一天啥都不幹:dp[i][j]=dp[i1][j](j[0,MaxP])dp[i][j]=dp[i-1][j](j\in [0,MaxP])

  2. 這一天在沒有票的基礎上買了一些票: dp[i][j]=min(dp[i][j],AP[i]j)(j[0,AS[i]])dp[i][j]=min(dp[i][j],-AP[i]*j)(j\in[0,AS[i]])

  3. 這一天在第iw1i-w-1天的基礎上賣了一些票:
    dp[i][j]=max(dp[i][j],max(dp[iw1][k]+(kj)BP[i]))(k[j+1,j+BS[i]])dp[i][j]=max(dp[i][j],max(dp[iw1][k]+kBP[i])jBP[i])(k[j+1,j+BS[i]]) dp[i][j]=max(dp[i][j],max(dp[i-w-1][k]+(k-j)*BP[i]))(k\in[j+1,j+BS[i]]) \\ \to dp[i][j]=max(dp[i][j], max(dp[i-w-1][k]+k*BP[i])-j*BP[i])(k\in[j+1,j+BS[i]])
    取值範圍是個滑動窗口, 單調隊列優化。

  4. 這一天在第iw1i-w-1天的基礎上買了一些票: 和上面的式子差不多。

所以兩個單調隊列就好了。 總複雜度O(TMaxP)O(TMaxP)

代碼如下:

#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]);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章