[SCOI2010]股票交易
阿新 • • 發佈:2018-01-04
-i pos push 事情 ble lin vector its down , 即從當天起直接購買。
[2] \(f[i][j] = f[i-1][j] ;\) , 即什麽都不做。
[3] \(f[i][j] = f[i-W-1][t] - (j-t)*Ap[i];(0<=t<=As[i])\),即購買股票。
[4] \(f[i][j] = f[i-W-1][t] + (t-j)*Bp[i];(0<=t<=Bs[i])\), 即賣出股票。
直接這樣轉移的時間復雜度為\(O(N^3)\)的,顯然過不去。
發現一個神奇的事情,[3]、[4]可以單調隊列優化。
不知道單調隊列優化的請戳這裏
以優化[3]為例,優化[4]是類似的。
原來的轉移方程:\(f[i][j] = f[i-W-1][t] - (j-t)*Ap[i];\)
拆開後移項:\(f[i][j] + Ap[i]*j = f[i-W-1][t] + Ap[i]*t\)
左右兩邊一模一樣,滿足單調隊列優化要求,大力跑即可。
註意在處理[4]的時候要逆序處理,原因滑稽自己yy一下啦
題目大意:
網址:https://www.luogu.org/problemnew/show/P2569
大意:在接下來的T天中,每天股票有一個買入價格Api與賣出價格Bpi。
同時,每天買入股票數與賣出股票數分別不能超過Asi與Bsi。
再者,兩次股票交易之間時間間隔必須小於W天,任一時刻持股數不能超過MaxP。
那麽假設初始時錢數無限,求解T天後的最大收入值(>=0)。
\(0<=W<T<=2000,1<=MaxP<=2000\)
題目解法:
DP,狀態太顯然了:\(f[i][j]\) 表示到了第i天,持有j股的最大收入額。
轉移也很容易:
[1] \(f[i][j] = -1*j*Ap[i] ;(j<=As[i])\)
[2] \(f[i][j] = f[i-1][j] ;\) , 即什麽都不做。
[3] \(f[i][j] = f[i-W-1][t] - (j-t)*Ap[i];(0<=t<=As[i])\),即購買股票。
[4] \(f[i][j] = f[i-W-1][t] + (t-j)*Bp[i];(0<=t<=Bs[i])\), 即賣出股票。
直接這樣轉移的時間復雜度為\(O(N^3)\)的,顯然過不去。
發現一個神奇的事情,[3]、[4]可以單調隊列優化。
不知道單調隊列優化的請戳這裏
以優化[3]為例,優化[4]是類似的。
原來的轉移方程:\(f[i][j] = f[i-W-1][t] - (j-t)*Ap[i];\)
拆開後移項:\(f[i][j] + Ap[i]*j = f[i-W-1][t] + Ap[i]*t\)
左右兩邊一模一樣,滿足單調隊列優化要求,大力跑即可。
註意在處理[4]的時候要逆序處理,原因
具體實現代碼:
include<bits/stdc++.h> #define maxn 2005 #define ll long long #define gi(x) scanf("%lld",&x); #define INF 1e16+7 using namespace std; const ll zero = 0; bool vis[maxn]; ll l1,l2,r1,r2,f[maxn][maxn],T,MaxP,W,Ap,Bp,As,Bs,Ans; struct Node{ll j,f;}; struct cmp{ bool operator ()(Node a,Node b){ return a.f < b.f;} }; priority_queue<Node,vector<Node>,cmp>Q; int main(){ gi(T); gi(MaxP); gi(W); for(ll i=0;i<=T;i++)for(ll j=0;j<=MaxP;j++)f[i][j]=-INF; f[0][0] = 0; for(ll i = 1; i <= T; i ++) { gi(Ap); gi(Bp); gi(As); gi(Bs); ll bf = max(zero,i-W-1); for(ll j = 0; j <= MaxP; j ++) f[i][j] = f[i-1][j]; for(ll j = 0; j <= min(MaxP,As); j ++) f[i][j] = max(f[i][j] , -1*Ap*j); while(!Q.empty())Q.pop(); for(ll j = 0; j <= MaxP; j ++){ l1 = max(j-As,zero); r1 = j; while(!Q.empty() && !(l1<=Q.top().j && Q.top().j<=r1))Q.pop(); Q.push((Node){j,f[bf][j] + Ap*j}); f[i][j] = max(f[i][j],Q.top().f - Ap*j); } while(!Q.empty())Q.pop(); for(ll j = MaxP; j >= 0; j --){ l2 = j; r2 = min(j+Bs,MaxP); while(!Q.empty() && !(l2<=Q.top().j && Q.top().j<=r2))Q.pop(); Q.push((Node){j,f[bf][j] + Bp*j}); f[i][j] = max(f[i][j],Q.top().f - Bp*j); } } Ans = 0; for(ll i = 0; i <= MaxP; i ++) Ans = max( Ans , f[T][i] ); cout<<Ans; return 0; }
[SCOI2010]股票交易