[SCOI2010]股票交易(单调队列优化dp)
[SCOI2010]股票交易
题目描述
最近lxhgww又迷上了投资股票,通过一段时间的观察和学习,他总结出了股票行情的一些规律。
通过一段时间的观察,lxhgww预测到了未来T天内某只股票的走势,第i天的股票买入价为每股APi,第i天的股票卖出价为每股BPi(数据保证对于每个i,都有APi>=BPi),但是每天不能无限制地交易,于是股票交易所规定第i天的一次买入至多只能购买ASi股,一次卖出至多只能卖出BSi股。
另外,股票交易所还制定了两个规定。为了避免大家疯狂交易,股票交易所规定在两次交易(某一天的买入或者卖出均算是一次交易)之间,至少要间隔W天,也就是说如果在第i天发生了交易,那么从第i+1天到第i+W天,均不能发生交易。同时,为了避免垄断,股票交易所还规定在任何时间,一个人的手里的股票数不能超过MaxP。
在第1天之前,lxhgww手里有一大笔钱(可以认为钱的数目无限),但是没有任何股票,当然,T天以后,lxhgww想要赚到最多的钱,聪明的程序员们,你们能帮助他吗?
输入输出格式
输入格式:
输入数据第一行包括3个整数,分别是T,MaxP,W。
接下来T行,第i行代表第i-1天的股票走势,每行4个整数,分别表示APi,BPi,ASi,BSi。
输出格式:
输出数据为一行,包括1个数字,表示lxhgww能赚到的最多的钱数。
输入输出样例
输入样例#1:
5 2 0
2 1 1 1
2 1 1 1
3 2 1 1
4 3 1 1
5 4 1 1
输出样例#1:
3
说明
对于30%的数据,0<=W<T<=50,1<=MaxP<=50
对于50%的数据,0<=W<T<=2000,1<=MaxP<=50
对于100%的数据,0<=W<T<=2000,1<=MaxP<=2000
对于所有的数据,1<=BPi<=APi<=1000,1<=ASi,BSi<=MaxP
前面的东西就不再赘述了,直接上转移方程。
状态转移方程:
1 . 凭空买
仅本情况下的状态可以直接赋值,其他状态初值为 \(-inf\),即:
\]
\]
下面三种情况,分别可列三个状态转移方程:
2 . 不买也不卖
最好想也最好列转移方程的一种情况,直接由上一天转移,且拥有股票数量不变。即:
\]
3 . 在之前的基础上买股票
这里的方程就比较复杂了,这里详细解释一下:
题目中指明说两次交易需要至少隔 \(w\) 天。也就是说,今天是第 i天交易,那么上一次交易最近是在第\(i-w-1\) 天。
可我第\(i-w-1\) 天之前也可以交易啊?为什么偏偏是那一天,而不是第\(i-w-2\)天?
回看刚刚讨论的第 2 种情况,我们已经把某一天以前的最优答案转移到了该天,所以从那一天转移,相当于从那一天包括前面任何一天开始转移,省去了大把时间。
接下来,我们已知第 \(i\)天拥有 \(j\)张股票,假设第\(i-w-1\)天拥有 \(k\)张股票。
\(k\)一定比 \(j\) 小,因为这一种情况是买股票,股票只能多。
但股票又不能买太多,限制最多为 \(as\) 张。所以 \(j - aSi\) 是底线。
继续,这次交易买了 \(j - k\)张股票,要花去\((j-k)*aPi\)元。
整理一下,转移方程为:
$$(j-aSi<=k<j)\]
4 . 在之前的基础上卖股票
和上面的情况特别类似,在此简单地说一下区别。
因为是卖股票, \(k\) 这次要比 \(j\)大。但要小于等于 \(j + bSi\)。
这次交易卖了 \(k - j\)张邮票,赚得\((k - j)*bPi\)元。
整理一下,转移方程为:
\]
\]
这个时候发现那两种情况,实际上可以使用单调性优化。此时达到降时间复杂度的目标。
就以第 3 种情况,在之前的基础上买股票为例子吧。
再重复提一下那个转移方程:
\]
\]
运用乘法分配率:
\]
\]
既然要将状态转移给F[i,j]此时j可以从 max中提取出,此时转移方程变为:
\]
\]
此时,我们发现以上的转移方程符合单调性优化的条件,故可以使用单调性优化。
还有一个细节,是第 3 种情况转移应该顺序,第 4 种情况转移应该逆序,这个不难理解,先自己想想吧。
其实就是,在考虑卖股票的时候,持有的股票越多是不是当前值会越大,我们为了使队首为最优解(即最大值),倒序即可。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
int read()
{
int x=0,w=1;char ch=getchar();
while(ch>'9'||ch<'0') {if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return x*w;
}
int dp[2010][2010],team1[2010],team2[2010];
struct node{
int ap,bp,as,bs;
}a[2010];
int main()
{
memset(dp,-0x7f,sizeof(dp));
int t=read(),maxx=read(),w=read();
for(int i=1;i<=t;i++)
{
a[i].ap=read();a[i].bp=read();
a[i].as=read();a[i].bs=read();
}
for(int i=1;i<=t;i++)
{
for(int j=0;j<=a[i].as;j++)
dp[i][j]=-a[i].ap*j;
for(int j=0;j<=maxx;j++)
{
dp[i][j]=max(dp[i][j],dp[i-1][j]);
}
if(i-w<=0) continue;
int l1=1,r1=0,l2=1,r2=0;
for(int j=0;j<=maxx;j++)
{
while(l1<=r1&&dp[i-w-1][team1[r1]]+a[i].ap*team1[r1]<=dp[i-w-1][j]+a[i].ap*j) r1--;
team1[++r1]=j;
while(l1<=r1&&j-team1[l1]>a[i].as) l1++;
if(l1<=r1)
dp[i][j]=max(dp[i][j],dp[i-w-1][team1[l1]]-a[i].ap*(j-team1[l1]));
}
for(int j=maxx;j>=0;j--)
{
while(l2<=r2&&dp[i-w-1][team2[r2]]+a[i].bp*team2[r2]<=dp[i-w-1][j]+a[i].bp*j) r2--;
team2[++r2]=j;
while(l2<=r2&&team2[l2]-j>a[i].bs) l2++;
if(l2<=r2)
dp[i][j]=max(dp[i][j],dp[i-w-1][team2[l2]]+a[i].bp*(team2[l2]-j));
}
/*for(int j=0;j<=maxx;j++)
{
if(j<=a[i].as)
dp[i][j]=-1*a[i].ap*j;
dp[i][j]=max(dp[i][j],dp[i-1][j]);
for(int k=0;k<=maxx;k++)
{
if(j>k&&j-k<=a[i].as&&i-w-1>0)
dp[i][j]=max(dp[i][j],dp[i-w-1][k]-a[i].ap*(j-k));
else if(j<k&&k-j<=a[i].bs&&i-w-1>0)
dp[i][j]=max(dp[i][j],dp[i-w-1][k]+a[i].bp*(k-j));
}
}*/
}
cout<<dp[t][0];
}
[SCOI2010]股票交易(单调队列优化dp)的更多相关文章
- 1855: [Scoi2010]股票交易[单调队列优化DP]
1855: [Scoi2010]股票交易 Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 1083 Solved: 519[Submit][Status] ...
- 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 ...
- 【bzoj1855】 [Scoi2010]股票交易 单调队列优化DP
上一篇blog已经讲了单调队列与单调栈的用法,本篇将讲述如何借助单调队列优化dp. 我先丢一道题:bzoj1855 此题不难想出O(n^4)做法,我们用f[i][j]表示第i天手中持有j只股票时,所赚 ...
- bzoj1855: [Scoi2010]股票交易 单调队列优化dp ||HDU 3401
这道题就是典型的单调队列优化dp了 很明显状态转移的方式有三种 1.前一天不买不卖: dp[i][j]=max(dp[i-1][j],dp[i][j]) 2.前i-W-1天买进一些股: dp[i][j ...
- LUOGU P2569 [SCOI2010]股票交易(单调队列优化dp)
传送门 解题思路 不难想一个\(O(n^3)\)的\(dp\),设\(f_{i,j}\)表示第\(i\)天,手上有\(j\)股的最大收益,因为这个\(dp\)具有单调性,所以\(f_i\)可以贪心的直 ...
- SCOI 股票交易 单调队列优化dp
这道题 我很蒙.....首先依照搞单调队列优化dp的一般思路 先写出状态转移方程 在想法子去优化 这个题目中说道w就是这一天要是进行操作就是从前w-1天转移而来因为之前的w天不允许有操作!就是与这些天 ...
- BZOJ 1855 股票交易 - 单调队列优化dp
传送门 题目分析: \(f[i][j]\)表示第i天,手中拥有j份股票的最优利润. 如果不买也不卖,那么\[f[i][j] = f[i-1][j]\] 如果买入,那么\[f[i][j] = max\{ ...
- BZOJ1855 股票交易 单调队列优化 DP
描述 某位蒟佬要买股票, 他神奇地能够预测接下来 T 天的 每天的股票购买价格 ap, 股票出售价格 bp, 以及某日购买股票的上限 as, 某日出售股票上限 bs, 并且每次股票交 ♂ 易 ( 购 ...
- 股票交易——单调队列优化DP
题目描述 思路 蒟蒻还是太弱了,,就想到半个方程就GG了,至于什么单调队列就更想不到了. $f[i][j]$表示第$i天有j$张股票的最大收益. 那么有四种选择: 不买股票:$f[i][j]=max( ...
- 2018.09.10 bzoj1855: [Scoi2010]股票交易(单调队列优化dp)
传送门 单调队列优化dp好题. 有一个很明显的状态设置是f[i][j]表示前i天完剩下了j分股票的最优值. 显然f[i][j]可以从f[i-w-1][k]转移过来. 方程很好推啊. 对于j<kj ...
随机推荐
- SpringBoot 参数校验
一.添加依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId> ...
- PCA(基础知识)
参考:http://blog.csdn.net/wangjian1204/article/details/50642732 参考:https://www.zhihu.com/question/3831 ...
- AndroidManifest.xml里加入不同package的component (Activity、Service里android:name里指定的值一般为句号加类名),可以通过指定完全类名(包名+类名)来解决
我们都知道对于多个Activity如果在同一个包中,在Mainfest中可以这样注册 <span style="font-size: small;"><?xml ...
- CF1037H Security 后缀自动机 + right集合线段树合并 + 贪心
题目描述: 给定一个字符串 $S$ 给出 $Q$ 个操作,给出 $L,R,T$,求出字典序最小的 $S_{1}$ 为 $S[L...R]$的子串,且 $S_{1}$ 的字典序严格大于 $T$. 输出这 ...
- 又联考了一场,感觉自己好菜啊,T2推出了公式但是不会逆元QAQ,难受啊!!!不过都确实是一道逆元的好题撒!
简单的玄学(random) 题目描述: 样例输入: 样例1: 3 2 样例2: 1 3 样例3: 4 3 样例输出: 样例1: 1 8 样例2: 1 1 样例3: 23 128 提示: 时间限制:10 ...
- Cocoapods组件化之搭建组件化项目框架
一,概述 随着公司业务需求的不断迭代发展,工程的代码量和业务逻辑也越来越多,原始的开发模式和架构已经无法满足我们的业务发展速度了,这时我们就需要将原始项目进行一次重构大手术了.这时我们应该很清晰这次手 ...
- 【转】Office 2003 EXCEL多窗口打开
转自:http://blog.csdn.net/god_is_gril/article/details/8992587 1.注册表备份开始/运行,输入regedit回车,打开注册表.在注册表界面定位到 ...
- centos7中yum安装lamp环境
一.准备工作 1.1 环境 操作系统:centos7(CentOS-7-x86_64-Minimal-1708) 硬件:(这个根据项目运行和配置建议设置,一般我先配个1核1G) 1.2 关闭selin ...
- vue获取v-on绑定事件的触发对象
<span @click="fn" id="foo">xxx</span> fn(e){ console.log(e);//展开查看e. ...
- 【转载】Stackless Python并发式编程介绍[已校对版]
Stackless Python并发式编程介绍[已校对版] 作者: Grant Olson 电子邮件: olsongt@verizon.net 日期: 2006-07-07 译者: ...