Question
Recently, \ (\ Text {lxhgww} \) became addicted to investing in stocks. After a period of observation and learning, he summed up some rules of stock quotations.
Through a period of observation, \ (\ Text {lxhgww} \) predicted the trend of a stock in the future \ (T \) Day, the \ (I \) the daily stock purchase price is per share \ (ap_ I \), and the sales price for the day of \ (I \) is per share \ (bp_ I \) (Data guarantee for each \ (I \), there are \ (ap_ I \ geq bp_ I \), but there is no limit to trading every day, so the stock exchange stipulates the \ (I \) up to \ (as_ I \) shares can be bought at a time every day, and up to \ (bs_ I \) shares can be sold at a time.
In addition, the stock exchange has two rules. In order to avoid crazy transactions, the stock exchange requires at least \ (w \) days between two transactions (buying or selling a day is regarded as one transaction, that is to say, if a transaction occurs on day \ (I \), no transaction can be performed from day \ (I + 1 \) to day \ (I + w. At the same time, in order to avoid monopoly, the stock exchange also stipulates that at any time, the number of shares in a person's hand cannot exceed \ (\ Text {maxp }\).
Before day \ (1 \), \ (\ Text {lxhgww} \) had a large amount of money (which can be considered as an infinite number of money), but there was no stock. Of course, \ (T \) days later, \ (\ Text {lxhgww} \) want to make the most money, smart programmers, can you help him?
Analysis
Set \ (f (I, j) \) to represent the maximum benefit of the \ (J \) stock held by the \ (I.
\ [F (I, j) = \ MAX \ left \ {\ begin {array} {}\ Max _ {k = 1} ^ {as_ I} f (I-w-1, J-K) -ap_ I \ times K \ Max _ {k = 1} ^ {bs_ I} f (I-w-1, J + k) + bp_ I \ times K \ f (I-1, J) \ end {array} \ right. \]
It is easy to conclude that the time complexity of this equation is \ (\ theta (N ^ 3 )\). Obviously \ (\ RM t \).
You can only buy \ (\ Max _ {k = 1} ^ {as_ I} f (I-w-1, J-k)-ap_ I \ times K, we found that the \ (f \) to be queried is always a continuous interval, but if we use monotonous queue maintenance \ (f \), \ (ap_ I \ times K \) it's disgusting.
However, we observe that for each \ (ap_ I \ times K \) and \ (bp_ I \ times K \) affected \ (f \), if \ (J + 1 \), \ (ap_ I \) or \ (-bp_ I \) are added at the same time \).
For example, the original \ (f (I-w-1, J)-ap_ I, \ f (I-w-1, J-1)-2ap_ I, \ cdots, f (I-w-1, J + k)-ap_ I \ times K \).
When the range is shifted to the right, their effect becomes: $ f (I-w-1, J-1)-ap_ I ,? F (I-w-1, J-2)-2ap_ I, \ cdots $
Therefore, when the range to be queried is shifted one time to the right, their relative size relationship will not change. We can view the original \ (\ rm dp \) to better use this property.
For example, \ (\ Max _ {k = 1} ^ {as_ I} f (I-w-1, J-k)-ap_ I \ times K \), if the \ (P = J-k \) order is set:
\ [\ Begin {array }{}& \ Max _ {P = J-1} ^ {J-as_ I} f (I-w-1, P) -ap_ I \ times (J-p) \\=& \ Max _ {P = J-1} ^ {J-as_ I} (f (I-w-1, P) + ap_ I \ times P)-ap_ I \ times J \ end {array} \]
In this way, \ (f \) and \ (ap_ I \) have a one-to-one ing relationship, and monotonous queue optimization can be easily used.
Similarly, you can use this method to sell data. The variable is \ (\ Max _ {P = J + 1} ^ {J + bs_ I} (f (I-w-1, P) + bp_ I \ times P)-bp_ I \ times J \).
The next step is the conventional monotonous queue optimization. the time complexity is \ (\ theta (N ^ 2 )\).
Code
#include <bits/stdc++.h>using namespace std;const int MAXN = 2000 + 5, inf = 0x3f3f3f3f;int f[MAXN][MAXN], ap[MAXN], bp[MAXN], as[MAXN], bs[MAXN], w, t, maxp;struct monQue { pair<int, int> data[MAXN]; int head, tail; void clear() {head = 0, tail = 0;} bool empty() {return tail <= head;} void push(pair<int, int> x) { while(!empty() && data[tail - 1] <= x) tail--; data[tail++] = x; } void pop() {head++;} pair<int, int> front() {return data[head];}} sell, buy;int main() { memset(f, ~0x3f, sizeof(f)); scanf("%d%d%d", &t, &maxp, &w); for(int i = 1; i <= t; i++) scanf("%d%d%d%d", &ap[i], &bp[i], &as[i], &bs[i]); for(int i = 1; i <= t; i++) { buy.clear(); sell.clear(); for(int j = 0; j <= maxp; j++) { f[i][j] = max(f[i - 1][j], f[i][j]); if(j <= as[i]) f[i][j] = max(-ap[i] * j, f[i][j]); if(i - w - 1 <= 0) continue; if(j) { while(!buy.empty() && buy.front().second < j - as[i]) buy.pop(); buy.push(make_pair(f[i - w - 1][j - 1] + ap[i] * (j - 1), j - 1)); f[i][j] = max(buy.front().first - ap[i] * j, f[i][j]); } } if(i - w - 1 <= 0) continue; for(int j = maxp - 1; j >= 0; j--) { while(!sell.empty() && sell.front().second > j + bs[i]) sell.pop(); sell.push(make_pair(f[i - w - 1][j + 1] + bp[i] * (j + 1), j + 1)); f[i][j] = max(sell.front().first - bp[i] * j, f[i][j]); } } int ans = -inf; for(int i = 0; i <= maxp; i++) { ans = max(f[t][i], ans); } printf("%d\n", ans); return 0;}
Postscript
Finally, I entered this trap ..
[Scoi 2010] stock trading