Luogu 2569 [SCOI2010]股票交易 (朴素动规转移 + 单调队列优化)
题意:
已知未来 N 天的股票走势,第 i 天最多买进 as [ i ] 股每股 ap [ i ] 元,最多卖出 bs [ i ] 股每股 bp [ i ] 元,且每天最多拥有 Mp 股,且每两次交易至少需要相隔 W 天,求最多能赚多少钱。
细节:
1、初始情况下有无限的资金,但是不能算作赚的钱。
2、对于交易的定义为:买进一次股或者买出一次股,也就是不能在同一天进行两种操作。
分析:
这题目根据题意不难发现它必定存在重复子结构,而且对于后面买卖股票的过程不会影响前方的收益情况,可以得到这可以用动态规划解决。
状态的构建也是显然的:dp [ i ][ j ] 表示第 i 天拥有 j 股的最大价值。
1、初值->负无穷???
若是 0 则在转移的时候将不会出现在没有赚钱的情况下去买股票的情况。
且每个可行状态 dp [ i ][ j ] = -ap [ i ] × j ( 0 ⩽ j ⩽ as [ i ] )
2、当前不买也不卖-> dp [ i ][ j ] = max ( dp [ i - 1 ][ j ], dp[ i ][ j ] )
3、当前需要买进股票,由于有 W 天间隔的限制,所以不难发现我们需要枚举当前这次贸易需要从哪一次交易转移而来,但是由于有第二类情况的存在,其实第 0 至 i - W - 1 这几天的交易最优值是单调不降的,所以最优的价值一定可以从 i - W - 1 天的状态转移而来,所以转移:
dp [ i ][ j ] = max ( dp [ i ][ j ] , dp[ i - W - 1 ][ k ] - ( j - k ) × ap [ i ] )
( max ( 0 , j - as [ i ] ) ⩽ k ⩽ j )
4、当前需要卖出股票,转移就是:
dp [ i ][ j ] = max ( dp [ i ][ j ] , dp[ i - W - 1 ][ k ] + ( k - j ) × bp [ i ] )
( j ⩽ k ⩽ min( Mp , j + bs [ i ] ) )
成功的写出了朴素的动态规划方程,现在考虑优化,由于 N ≤ 2000 且 Mp ≤ 2000 这个 2D / 1D 的动态规划显然不能 AC ,比如把 3 的式子进行转化:
dp [ i ][ j ] = max { dp [ i - W - 1][ k ] + k × ap [ i ] } - j × ap [ i ]
显然又转化成一个定区间求最值的模型,就可以使用单调队列解决了,4 式的转化同理可得,在转移时可以令 j 从 Mp 开始往 0 进行转移,按序加入队列中。
代码:
#include<bits/stdc++.h>
#define Inf 1000000000
#define MAXN 2005
using namespace std;
int f[MAXN][MAXN], ap[MAXN], bp[MAXN], as[MAXN], bs[MAXN];
int n, Mp, w, que1[MAXN], que2[MAXN];
int main(){
scanf("%d%d%d", &n, &Mp, &w);
for (int i=1; i<=n; i++) scanf("%d%d%d%d", &ap[i], &bp[i], &as[i], &bs[i]);
for (int i=0; i<=n; i++)
for (int j=0; j<=Mp; j++) f[i][j]=-Inf;
for (int i=1; i<=n; i++)
for (int j=0; j<=as[i]; j++) f[i][j]=-j*ap[i];
for (int i=1; i<=n; i++){
for (int j=0; j<=Mp; j++) f[i][j]=max(f[i][j], f[i-1][j]);
int head1=1, head2=1, tail1=0, tail2=0;
for (int j=0; j<=Mp; j++){
while (head1<=tail1 && que1[head1]<max(j-as[i], 0)) ++head1;
if (head1<=tail1) f[i][j]=max(f[i][j], f[max(0, i-w-1)][que1[head1]]-(j-que1[head1])*ap[i]);
while (head1<=tail1 && f[max(i-w-1, 0)][que1[tail1]]+que1[tail1]*ap[i]<=f[max(i-w-1, 0)][j]+j*ap[i]) --tail1;
que1[++tail1]=j;
}
for (int j=Mp; j>=0; j--){
while (head2<=tail2 && que2[head2]>min(Mp, j+bs[i])) ++head2;
if (head2<=tail2) f[i][j]=max(f[i][j], f[max(0, i-w-1)][que2[head2]]+(que2[head2]-j)*bp[i]);
while (head2<=tail2 && f[max(i-w-1, 0)][que2[tail2]]+que2[tail2]*bp[i]<=f[max(0, i-w-1)][j]+j*bp[i]) --tail2;
que2[++tail2]=j;
}
}
int Ans=-Inf;
for (int i=0; i<=Mp; i++) Ans=max(Ans, f[n][i]);
printf("%d\n", Ans);
return 0;
}
Luogu 2569 [SCOI2010]股票交易 (朴素动规转移 + 单调队列优化)的更多相关文章
- 洛谷 P2569[SCOI2010]股票交易(动规+单调队列)
//只能写出裸的动规,为什么会有人能想到用单调队列优化Orz 题目描述 最近lxhgww又迷上了投资股票,通过一段时间的观察和学习,他总结出了股票行情的一些规律. 通过一段时间的观察,lxhgww预测 ...
- BZOJ1855或洛谷2569 [SCOI2010]股票交易
一道单调队列优化\(DP\) BZOJ原题链接 洛谷原题链接 朴素的\(DP\)方程并不难想. 定义\(f[i][j]\)表示到第\(i\)天,手上持有\(j\)股时的最大收益. 转移方程可以分成四个 ...
- Luogu P2569 [SCOI2010] 股票交易
此题链接到dp常见优化方法 开始的时候被纪念品误导,以为是多支股票,后来发现事情不妙: 这道题知道的是某一只股票的走势: \(Solution\): \(70pts\): 设\(f[i][j]\)表示 ...
- LUOGU P2569 [SCOI2010]股票交易(单调队列优化dp)
传送门 解题思路 不难想一个\(O(n^3)\)的\(dp\),设\(f_{i,j}\)表示第\(i\)天,手上有\(j\)股的最大收益,因为这个\(dp\)具有单调性,所以\(f_i\)可以贪心的直 ...
- 1855: [Scoi2010]股票交易[单调队列优化DP]
1855: [Scoi2010]股票交易 Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 1083 Solved: 519[Submit][Status] ...
- P2569 [SCOI2010]股票交易 dp 单调队列优化
LINK:股票交易 题目确实不算难 但是坑点挺多 关于初值的处理问题我就wa了两次. 所以来谢罪. 由于在手中的邮票的数量存在限制 且每次买入卖出也有限制. 必然要多开一维来存每天的邮票数量. 那么容 ...
- 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 ...
- 【Luogu】P2569股票交易(单调队列优化DP)
题目链接 首先这题可以肯定的是朴素DP秒出.然后单调队列优化因为没接触过所以不会emmm 而且脑补没补出来 坐等四月省选倒数第一emmm 心态爆炸,偷懒放题解链接 #include<cstdio ...
随机推荐
- VMware每次联网都需要还原默认设置解决办法
参考:https://zhidao.baidu.com/question/553464573715382812.html
- VMware下OSSIM 5.2.0的下载、安装和初步使用(图文详解)
不多说,直接上干货! 入门阶段不建议选用最新的版本. 采用OSSIM 4.11 到 OSSIM5.0.3 之间任何版本做实验,sensor的状态都会是“V”. 建议,入门,采用OSSIM5.0.0 ...
- 181. 将整数A转换为B
181. 将整数A转换为B 如果要将整数A转换为B,需要改变多少个bit位? 注意事项 Both n and m are 32-bit integers. 您在真实的面试中是否遇到过这个题? Yes ...
- session是什么时候创建的
总结:session不是一打开网站就会立刻建立.它的建立需要基于下面两个条件中的任意一个: 1:在servlet中手动调用 HttpSession session = request.getSessi ...
- mongodb备份、还原
1.mongodb 备份 mongodump 命令可以使用可用的选项的列表. 此命令将仅备份指定的数据库,在指定的路径 语法 描述 示例 mongodump --host HOST_NAME --p ...
- HDU4576 Robot(概率)
题意 抄袭自https://www.cnblogs.com/Paul-Guderian/p/7624039.html 多组输入n,m,l,r.表示在一个环上有n个格子.接下来输入m个w表示连续的一段 ...
- Android 6.0 运行时权限处理完全解析 (摘抄)
转载请标明出处: http://blog.csdn.net/lmj623565791/article/details/50709663: 本文出自:[张鸿洋的博客] 一.概述 随着Android 6. ...
- 洛谷 P2292 [HNOI2004]L语言
题目描述 标点符号的出现晚于文字的出现,所以以前的语言都是没有标点的.现在你要处理的就是一段没有标点的文章. 一段文章T是由若干小写字母构成.一个单词W也是由若干小写字母构成.一个字典D是若干个单词的 ...
- [习题]输入自己的生日(年/月/日)#2 -- 日历(Calendar)控件的时光跳跃,一次跳回五年、十年前?--TodaysDate属性、VisibleDate属性
原文出處 http://www.dotblogs.com.tw/mis2000lab/archive/2013/06/10/calendar_visibledate_birthday_dropdow ...
- codeforces Gym 100338H High Speed Trains (递推,高精度)
递推就好了,用二项式定理算出所有连边的方案数,减去不合法的方案, 每次选出一个孤立点,那么对应方案数就是上次的答案. 枚举选几个孤立点和选哪些,选到n-1个点的时候相当于都不选,只减1. 要用到高精度 ...