【BZOJ1855】[Scoi2010] 股票交易
很显然的动态规划题(笑)
容易想到DP的数组 f[i][j] 表示第i天手上有j股股票时能赚到最多的钱。
接下来就是转移了,有这么多变量一定要看清楚,仔细地分情况讨论。
每次转移时一共有四种情况:
(先从简单的入手)
一、第i天不买股票也不买
那就是从前一天相同的股票值更新过来
f[i][j]=max(f[i][j],f[i-1][j]);
那为什么是前一天而不是前几天呢?因为前几天的最优值都已经更新到前一天了呀。
二、第i天凭空买股票(相当于从之前手持0股票的情况更新来)
其实就是第i天的DP数组的初始化
For(j,0,As[i]) f[i] [j]=-1 * j * Ap[i];
三、第i天在第 i-w-1 天的基础上买股票
那我们设第i-w-1天的股票数为k,最直接的更新就是下面这样
f[i][j]=max(f[i][j], f[i-w-1][k]-(j-k)* Ap[i]);
但我们此时要更新的是j,所以可以稍稍转化一下:
f[i][j]=max{ f[i-w-1][k]+k*Ap[i] } - j* Ap[i]
那么此时k的范围是多少呢 不难想到就是 [ j-As[i], j)
所以在k的取值范围上,有经验的OIer们应该都能想到单调队列了吧(!)
式子中有取max值,还有取值范围的经常都是用单调队列来优化(不知道具体如何操作的可以看代码)
四、第i天在第i-w-1天的基础上卖出股票
和上一种情况其实是一样的(式子的推导请参照上式自己操作)
f[i][j]=max{f[i-w-1][k]+k*Bp[i]}- j* Ap[i]
只是k的取值范围不一样了,变成了(j, j+Bs[i] ]
同样可以用单调队列来优化。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm> #define For(i,a,b) for(register int i=a;i<=b;++i)
#define Dwn(i,a,b) for(register int i=a;i>=b;--i)
#define Re register using namespace std; const int N=2e3+;
int f[N][N],q[N*],qf,qr;
int n,m,As[N],Ap[N],Bs[N],Bp[N],W,T,MaxP;
inline void read(int &v){
v=;
char c=getchar();
while(c<''||c>'')c=getchar();
while(c>=''&&c<='')v=v*+c-'',c=getchar();
}
int main(){
read(T); read(MaxP); read(W);
For(i,,T){
read(Ap[i]); read(Bp[i]);
read(As[i]); read(Bs[i]);
}
memset(f,,sizeof(f));
For(i,,T){
// I bought some stocks from nowhere
For(j,,As[i]){
f[i][j]=-*j*Ap[i];
}
// I didn't buy anything
For(j,,MaxP){
f[i][j]=max(f[i][j],f[i-][j]);
} if(i-W-<=)continue; // I bought some stock today after W days
qf=; qr=;
For(j,,MaxP){
while(qf<=qr&&q[qf]<j-As[i])qf++;
if(qf<=qr){
int k=q[qf];
f[i][j]=max(f[i][j],f[i-W-][k]+k*Ap[i]-j*Ap[i]);
}
while(qf<=qr&&f[i-W-][q[qr]]+q[qr]*Ap[i]<=f[i-W-][j]+j*Ap[i])qr--;
q[++qr]=j;
} // I sold some stock today after W days
qf=; qr=;
Dwn(j,MaxP,){
while(qf<=qr&&q[qf]>j+Bs[i])qf++;
if(qf<=qr){
int k=q[qf];
f[i][j]=max(f[i][j],f[i-W-][k]+k*Bp[i]-j*Bp[i]);
}
while(qf<=qr&&f[i-W-][q[qr]]+q[qr]*Bp[i]<=f[i-W-][j]+j*Bp[i])qr--;
q[++qr]=j;
}
}
int fn=-;
For(i,,MaxP)fn=max(fn,f[T][i]);
cout<<fn<<endl;
return ;
}
【BZOJ1855】[Scoi2010] 股票交易的更多相关文章
- [bzoj1855][Scoi2010]股票交易_动态规划_单调队列
股票交易 bzoj-1855 Scoi-2010 题目大意:说不明白题意系列++...题目链接 注释:略. 想法:这个题还是挺难的. 动态规划没跑了 状态:dp[i][j]表示第i天手里有j个股票的最 ...
- BZOJ1855 [Scoi2010]股票交易 【单调队列优化dp】
题目链接 BZOJ1855 题解 设\(f[i][j]\)表示第\(i\)天结束时拥有\(j\)张股票时的最大收益 若\(i \le W\),显然在这之前不可能有交易 \[f[i][j] = max\ ...
- 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]股票交易
Description 最近lxhgww又迷上了投资股票,通过一段时间的观察和学习,他总结出了股票行情的一些规律. 通过一段时间的观察,lxhgww预测到了未来T天内某只股票的走势,第i天的股票买入价 ...
- 2018.09.10 bzoj1855: [Scoi2010]股票交易(单调队列优化dp)
传送门 单调队列优化dp好题. 有一个很明显的状态设置是f[i][j]表示前i天完剩下了j分股票的最优值. 显然f[i][j]可以从f[i-w-1][k]转移过来. 方程很好推啊. 对于j<kj ...
- 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 ...
- BZOJ1855 [Scoi2010]股票交易[单调队列dp]
题 题面有点复杂,不概括了. 后面的状态有前面的最优解获得大致方向是dp.先是瞎想了个$f[i][j]$表示第$i$天手里有$j$张股票时最大收入(当天无所谓买不买). 然后写了一个$O(n^4)$状 ...
- 洛谷P2569 (BZOJ1855)[SCOI2010]股票交易 【单调队列优化DP】
Description 最近lxhgww又迷上了投资股票,通过一段时间的观察和学习,他总结出了股票行情的一些规律. 通过一段时间的观察,lxhgww预测到了未来T天内某只股票的走势,第i天的股票买入价 ...
- 【BZOJ1855】[Scoi2010]股票交易 DP+单调队列
[BZOJ1855][Scoi2010]股票交易 Description 最近lxhgww又迷上了投资股票,通过一段时间的观察和学习,他总结出了股票行情的一些规律. 通过一段时间的观察,lxhgww预 ...
- 【BZOJ1855】股票交易(动态规划,单调队列)
[BZOJ1855]股票交易(动态规划,单调队列) 题面 BZOJ 题解 很显然,状态之和天数以及当天剩余的股票数有关 设\(f[i][j]\)表示第\(i\)天进行了交易,剩余股票数为\(j\)的最 ...
随机推荐
- Go怎么获取当前时间? Go ARM64 vDSO优化之路
https://mzh.io/ Go ARM64 vDSO优化之路 2018-03-16 | Meng Zhuo 背景 Go怎么获取当前时间?问一个会Go的程序员,他随手就能写这个出来给你. imp ...
- 记录一次MySQL两千万数据的大表优化解决过程,提供三种解决方案(转)
问题概述 使用阿里云rds for MySQL数据库(就是MySQL5.6版本),有个用户上网记录表6个月的数据量近2000万,保留最近一年的数据量达到4000万,查询速度极慢,日常卡死.严重影响业务 ...
- Shell之内容匹配与格式输出
对于大文本或者有些特定格式的文本,有时我们要查找特定内容或定位指定的区域,这样就需要内容匹配. 关于内容匹配,我们常使用的有几个命令: grep,支持正则,查找包含有匹配项的行. cut,提取指定的列 ...
- angularjs ng-repeat倒叙
<div ng-app="myApp" ng-controller="customersCtrl"> <table> <tr ng ...
- UVA 11752 The Super Powers —— 数学与幂
题目链接:https://vjudge.net/problem/UVA-11752 题解: 1.首先变量必须用unsig long long定义. 2.可以分析得到,当指数为合数的时候,该值合法. 3 ...
- Oracle数据查看被锁住的用户
//lock_date是被锁住时间,如果为空证明这个用户没有被锁住 select username,lock_date from dba_users where username='GFMIS'; ...
- 脚踏实地学C#3-装箱和拆箱
装箱:一种接受值类型的值,根据这个值在堆中创建一个完整的引用类型对象并返回对象的引用(堆地址)的隐式转换 int i_number = 2; //在栈中声明int类型i_Number变量并初始化 ob ...
- [ZJOI 2007] 捉迷藏
[题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=1095 [算法] 首先建出点分树,然后每一个点开两个堆.“第一个堆记录子树中所有节点到 ...
- 如何应用AutoIt,把局域网中所有的机器名展示在一个combox中?
有时候,我们会遇到以下情况: 你想与局域网中的某台机器建立连接,你就需要输入对方的机器名. 现在我比较懒,我不想输入对方的机器名,或者对方的机器名很难记住,那怎么办呢? 那就做一个combox在页面上 ...
- HDU2444(二分图判定+最大匹配)
The Accomodation of Students Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 32768/32768 K ( ...