P2569 [SCOI2010]股票交易
作者:互联网
令$f[i,j]$表示$i$天有$j$支股票的最大收益
有四种决策:不买不卖,不在之前的基础上买,买,卖
有
$$f[i,j] = max\begin{cases}
f[i-1,j]\\
-ap_i*j\\
\underset{max(j-as_i,0) \leq k < j}{max}\left \{ f[i-w-1,k]+ap_i*k \right \}-ap_i*j\\
\underset{j < k \leq min(bs_i+j,MaxP)}{max}\left \{ f[i-w-1,k]+bp_i*k \right \}-bp_i*j
\end{cases}$$
三四式就可以单掉队列优化
时间复杂度 $O(n*m)$
空间复杂度 $O(n*m)$
代码如下
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cstring> 5 #include <cmath> 6 #define ll long long 7 using namespace std; 8 9 template <typename T> void in(T &x) { 10 x = 0; T f = 1; char ch = getchar(); 11 while(!isdigit(ch)) {if(ch == '-') f = -1; ch = getchar();} 12 while(isdigit(ch)) {x = 10*x + ch - '0'; ch = getchar();} 13 x *= f; 14 } 15 //------------------------------------------------------------ 16 17 const int N = 2005; 18 19 int n,m,w; 20 int l,r,q[N],as[N],bs[N]; 21 ll ap[N],bp[N],f[N][N]; 22 23 ll calc(int i,int k,int op) { 24 return f[i-w-1][k]+ (op == 1 ? ap[i] : bp[i])*k; 25 } 26 27 int main() { 28 int i,j; in(n); in(m); in(w); 29 for(i = 1;i <= n; ++i) { 30 in(ap[i]); in(bp[i]); in(as[i]); in(bs[i]); 31 } 32 memset(f,~0x3f,sizeof(f)); 33 f[0][0] = 0; 34 for(i = 1;i <= n; ++i) { 35 for(j = 0;j <= as[i]; ++j) f[i][j] = -ap[i]*j; 36 for(j = 0;j <= m; ++j) f[i][j] = max(f[i][j],f[i-1][j]); 37 if(i-w-1 < 0) continue; 38 l = 1;r = 0; 39 for(j = 0;j <= m; ++j) { 40 while(l <= r && q[l] < max(0,j-as[i])) ++l; 41 if(l <= r) f[i][j] = max(f[i][j],calc(i,q[l],1)-ap[i]*j); 42 while(l <= r && calc(i,q[r],1) <= calc(i,j,1)) --r; 43 q[++r] = j; 44 } 45 l = 1,r = 0; 46 for(j = m;j >= 0; --j) { 47 while(l <= r && q[l] > min(m,bs[i]+j)) ++l; 48 if(l <= r) f[i][j] = max(f[i][j],calc(i,q[l],2)-bp[i]*j); 49 while(l <= r&& calc(i,q[r],2) <= calc(i,j,2)) --r; 50 q[++r] = j; 51 } 52 } 53 ll ans = 0; 54 for(i = 0;i <= m; ++i) ans = max(ans,f[n][i]); 55 cout << ans; 56 return 0; 57 }
标签:ch,ap,int,max,P2569,bp,股票交易,include,SCOI2010 来源: https://www.cnblogs.com/mzg1805/p/11442766.html