P2569 [SCOI2010]股票交易

${\color{Pink}{>>Question}}$

令$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 }

 

转载于:https://www.cnblogs.com/mzg1805/p/11442766.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值