【bzoj1855】 [Scoi2010]股票交易

上一篇blog已经讲了单调队列与单调栈的用法,本篇将讲述如何借助单调队列优化dp。

我先丢一道题:bzoj1855

此题不难想出O(n^4)做法,我们用f[i][j]表示第i天手中持有j只股票时,所赚钱的最大值。

不难推出以下式子:

$f[i][j]=max\left\{
\begin{aligned}
f[k][l]+(l-j)\times bs[i] , l \in [j,j+bs[i]]\\
f[k][l]-(j-l)\times as[i] , l \in [j-as[i],j]\\
\end{aligned}
\right \}
k \in [1,i-w]$

考虑到第i天持有的j只股票不一定全是第i天购买的,则对于$\forall j$,有$f[i][j]≥f[i][j-1]$,式子可化为O(n^3),变为:

$f[i][j]=max\left\{
\begin{aligned}
f[i-w-1][l]+(l-j)\times bs[i] , l \in [j,j+bs[i]]\\
f[i-w-1][l]-(j-l)\times as[i] , l \in [j-as[i],j]\\
\end{aligned}
\right \}$

考虑到$i,j≤1000$,如采用此做法依然会TLE,我们考虑采用单调队列进行优化,以下以卖出股票举例:

我们设$k<l<j$,我们认为$f[i-w-1][k]$比$f[i-w-1][l]$优,则必然满足$f[i-w-1][k]>f[i-1-1][l]+(k-l) \times bp[i]$。

我们对于每一个$i$,维护一个$f[i-w-1]$的单调队列,采用上述的判定机制删除非最优元素,同时考虑到$k,l$应位于区间$[j,j+bs[i]]$中,则需从队头删除下标不位于该区间的元素,最优用队头元素更新f[i][j]即可。

买入同理。

 1 #include<bits/stdc++.h>
 2 #define M 4010
 3 using namespace std;
 4 int f[M][M/2]={0},ap[M]={0},bp[M]={0},as[M]={0},bs[M]={0};
 5 int t,n,w,head,tail,q[M]={0},id[M]={0};
 6 int main(){
 7     scanf("%d%d%d",&t,&n,&w);
 8     for(int i=w+1;i<=t+w;i++) scanf("%d%d%d%d",ap+i,bp+i,as+i,bs+i);
 9     for(int i=0;i<=w;i++)
10     for(int j=1;j<=n;j++) f[i][j]=-1234567890;
11     for(int i=w+1;i<=t+w;i++){
12         for(int j=0;j<=n;j++) f[i][j]=f[i-1][j];
13         head=tail=0;
14         for(int j=1;j<=n;j++){
15             if(head<tail&&id[head+1]<j-as[i]) head++;
16             while(head<tail&&q[tail]-f[i-w-1][j-1]<((j-1)-id[tail])*ap[i]) tail--;
17             q[++tail]=f[i-w-1][j-1]; id[tail]=j-1;
18             if(head<tail) f[i][j]=max(f[i][j],q[head+1]-(j-id[head+1])*ap[i]);
19         }
20         head=tail=0;
21         for(int j=n-1;j>=0;j--){
22             if(head<tail&&j+bs[i]<id[head+1]) head++;
23             while(head<tail&&f[i-w-1][j+1]-q[tail]>(id[tail]-(j+1))*bp[i]) tail--;
24             q[++tail]=f[i-w-1][j+1]; id[tail]=j+1;
25             if(head<tail) f[i][j]=max(f[i][j],q[head+1]+(id[head+1]-j)*bp[i]);
26         }
27     }
28     printf("%d\n",f[t+w][0]);
29 }

原文地址:https://www.cnblogs.com/xiefengze1/p/8495754.html

时间: 2024-10-12 12:37:58

【bzoj1855】 [Scoi2010]股票交易的相关文章

BZOJ1855 [Scoi2010]股票交易 【单调队列优化dp】

题目链接 BZOJ1855 题解 设\(f[i][j]\)表示第\(i\)天结束时拥有\(j\)张股票时的最大收益 若\(i \le W\),显然在这之前不可能有交易 \[f[i][j] = max\{f[i - 1][j],-ap[i] * j\} \quad [j \le as[i]]\] 否则,就有三种选择: ①购买 \[f[i][j] = max\{f[i - W - 1][k] - ap[i] * (j - k)\} \quad[k \le j][j - k \le as[i]]\]

bzoj1855: [Scoi2010]股票交易--单调队列优化DP

单调队列优化DP的模板题 不难列出DP方程: 对于买入的情况 由于dp[i][j]=max{dp[i-w-1][k]+k*Ap[i]-j*Ap[i]} AP[i]*j是固定的,在队列中维护dp[i-w-1][k]+k*Ap[i]的单调性即可 1 #include<stdio.h> 2 #include<string.h> 3 #include<algorithm> 4 using namespace std; 5 const int maxn = 2010; 6 int

Bzoj1855: [Scoi2010]股票交易

题面 Bzoj Sol 设\(f[i][j]\)表示第\(i\)天有\(j\)张股票的最大收益 转移很简单辣 # include <bits/stdc++.h> # define RG register # define IL inline # define Fill(a, b) memset(a, b, sizeof(a)) using namespace std; typedef long long ll; const int _(2010); IL int Input(){ RG int

1855: [Scoi2010]股票交易[单调队列优化DP]

1855: [Scoi2010]股票交易 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 1083  Solved: 519[Submit][Status][Discuss] Description 最近lxhgww又迷上了投资股票,通过一段时间的观察和学习,他总结出了股票行情的一些规律. 通过一段时间的观察,lxhgww预测到了未来T天内某只股票的走势,第i天的股票买入价为每股APi,第i天的股票卖出价为每股BPi(数据保证对于每个i,都有APi>=

洛谷P2569 [SCOI2010]股票交易

P2569 [SCOI2010]股票交易 题目描述 最近lxhgww又迷上了投资股票,通过一段时间的观察和学习,他总结出了股票行情的一些规律. 通过一段时间的观察,lxhgww预测到了未来T天内某只股票的走势,第i天的股票买入价为每股APi,第i天的股票卖出价为每股BPi(数据保证对于每个i,都有APi>=BPi),但是每天不能无限制地交易,于是股票交易所规定第i天的一次买入至多只能购买ASi股,一次卖出至多只能卖出BSi股. 另外,股票交易所还制定了两个规定.为了避免大家疯狂交易,股票交易所规

[SCOI2010]股票交易

[SCOI2010]股票交易 推荐的相关题目显示 题目描述 最近 lxhgww 又迷上了投资股票,通过一段时间的观察和学习,他总结出了股票行情的一些规律. 通过一段时间的观察,lxhgww 预测到了未来 T 天内某只股票的走势,第 i 天的股票买入价为每股 APi?,第 i 天的股票卖出价为每股 BPi?(数据保证对于每个 i,都有 APi?≥BPi?),但是每天不能无限制地交易,于是股票交易所规定第 i 天的一次买入至多只能购买 ASi? 股,一次卖出至多只能卖出 BSi? 股. 另外,股票交

bzoj 1855: [Scoi2010]股票交易

Description 最近lxhgww又迷上了投资股票,通过一段时间的观察和学习,他总结出了股票行情的一些规律. 通过一段时间的观察,lxhgww预测到了未来T天内某只股票的走势,第i天的股票买入价为每股APi,第i天的股票卖出价为每股BPi(数据保证对于每个i,都有APi>=BPi),但是每天不能无限制地交易,于是股票交易所规定第i天的一次买入至多只能购买ASi股,一次卖出至多只能卖出BSi股. 另外,股票交易所还制定了两个规定.为了避免大家疯狂交易,股票交易所规定在两次交易(某一天的买入或

BZOJ 1855 [Scoi2010]股票交易 单调队列优化DP

题意:链接 方法:单调队列优化DP 解析:噢又是一道情况很多的题,然而三种更新我又落下一种导致样例不过,后来看题解才恍然- -最SB的一种更新居然忘了. 状态好想f[i][j]代表前i天有j双袜子时的最大利润. 三种更新: 第一种:f[i][j]=max(f[i][j],f[i?1][j]):(然而我忘了这一种) 第二种:买入f[i][j]=max(f[i][j],f[i?w?1][k]?(j?k)?a[i].ap)(k>=j?a[i].as); 第三种:卖出f[i][j]=max(f[i][j

●BZOJ 1855 [Scoi2010]股票交易

题链: http://www.lydsy.com/JudgeOnline/problem.php?id=1855 题解: DP,单调队列优化.(好久没做 DP题,居然还意外地想出来了) 定义 dp[i][k] 表示前 i天,手上还有 k股的最大收益.(注意这个定义是个前缀的形式)假设枚举到了第 i天,令 j=i-W-1.那么dp[i][]就由dp[j][]转移而来.(说了是前缀形式的啦,就不要去枚举 j-1,j-2...了)转移还是比较显然的:枚举第 i 天结束手上还剩的股数 k: