股票交易——单调队列优化DP
题目描述

思路
蒟蒻还是太弱了,,就想到半个方程就GG了,至于什么单调队列就更想不到了。
$f[i][j]$表示第$i天有j$张股票的最大收益。
那么有四种选择:
- 不买股票:$f[i][j]=max(f[i][j],f[i-1][j])$
- 买$j$张股票,之前没有买:$f[i][j]=-j*ap[i]$
- 买$j$张股票,之前有过交易,中间间隔了$w$天:$f[i][j]=max(f[i][j],f[i-w-1][k]-(j-k)*ap[i])$
- 卖$j$张股票,之前有过交易(废话),中间间隔了$w$天,$f[i][j]=max(f[i][j],f[i-w-1][k]+(k-j)*bp[i])$
方程列出来了,还是很好理解的。那么怎么优化呢?我们发现$i,j,k$都要枚举$O(n^3)$的复杂度是会$T$的,我们需要用一些优化。
我们发现:3转移中$f[i-w-1][k]-(j-k)*ap[i]=f[i-w-1][k]+k*ap[i]-j*ap[i]$,这样我们在第i天时只要找出最大的$f[i-w-1][k]+k*ap[i]$即可,因为前两维$i,j$已知,$j*ap[i]$是常数。
用一个递减的单调队列维护使$f[i-w-1][k]+k*ap[i]$最大的$k$,每次取队首转移即可,注意如果$as[i]<j-k$(即买不了这么多股票)时,需要把队首弹出。那么4也是一样,维护最大的$f[i-w-1][k]+k*bp[i](bs[i]<k-j)$
code
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int N=;
int n,m,w,ap,bp,as,bs;
int f[N][N],q[N],head,tail; int main()
{
scanf("%d%d%d",&n,&m,&w);
memset(f,,sizeof(f));//负无穷
for(int i=;i<=n;i++)
{
scanf("%d%d%d%d",&ap,&bp,&as,&bs);
for(int j=;j<=as;j++)f[i][j]=-ap*j;//转移2
for(int j=;j<=m;j++)f[i][j]=max(f[i-][j],f[i][j]);//转移1
if(i<=w)continue;//之前不能进行交易
head=,tail=;
for(int j=;j<=m;j++)
{
while(head<=tail&&q[head]<j-as)
head++;//不够买
while(head<=tail&&f[i-w-][q[tail]]+q[tail]*ap<=f[i-w-][j]+j*ap)
tail--;//单调性
q[++tail]=j;//加入新元素
if(head<=tail)
f[i][j]=max(f[i][j],f[i-w-][q[head]]+q[head]*ap-j*ap);//转移3
}
head=,tail=;
for(int j=m;j>=;j--)
{
while(head<=tail&&q[head]>j+bs)
head++;//不够卖
while(head<=tail&&f[i-w-][q[tail]]+q[tail]*bp<=f[i-w-][j]+j*bp)
tail--;//单调性
q[++tail]=j;//加入新元素
if(head<=tail)
f[i][j]=max(f[i][j],f[i-w-][q[head]]+q[head]*bp-j*bp);//转移4
}
}
cout<<f[n][];//最后一天全部卖出即为最优
}
股票交易——单调队列优化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只股票时,所赚 ...
- SCOI 股票交易 单调队列优化dp
这道题 我很蒙.....首先依照搞单调队列优化dp的一般思路 先写出状态转移方程 在想法子去优化 这个题目中说道w就是这一天要是进行操作就是从前w-1天转移而来因为之前的w天不允许有操作!就是与这些天 ...
- 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\)可以贪心的直 ...
- 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, 并且每次股票交 ♂ 易 ( 购 ...
- 2018.09.10 bzoj1855: [Scoi2010]股票交易(单调队列优化dp)
传送门 单调队列优化dp好题. 有一个很明显的状态设置是f[i][j]表示前i天完剩下了j分股票的最优值. 显然f[i][j]可以从f[i-w-1][k]转移过来. 方程很好推啊. 对于j<kj ...
随机推荐
- mac下的环境变量
a. /etc/profile b. /etc/paths c. ~/.bash_profile d. ~/.bash_login e. ~/.profile f. ~/.bashrc 其中a和b是系 ...
- 从0开始学FreeRTOS-(创建任务)-2
# 补充 开始今天的内容之前,先补充一下上篇文章[从单片机到操作系统-1](https://jiejietop.gitee.io/freertos-1/)的一点点遗漏的知识点. ```js BaseT ...
- 【TencentOS tiny】 超详细的TencentOS tiny移植到STM32F103全教程
移植前的准备工作 1. 获取STM32的裸机工程模板 STM32的裸机工程模板直接使用野火STM32开发板配套的固件库例程即可.可以从我github上获取https://github.com/jiej ...
- web 前端优化-戈多编程
大家好,我是戈多,从事web开发工作接近三年了,今天来归纳下web前端优化的解决方案(码农搬砖工,来自各网络汇总) 1.减少Http请求 http请求越多,那么消耗的时间越多,如果在加上网络很糟糕,那 ...
- e课表项目第二次冲刺周期第六天
昨天干了什么? 昨天是这次冲刺周期的第五天,我们的冲刺周期已经快过了一半,我们已经实现了对第一层界面的设计,所以我们的进度和我们的时间正好吻合,所以我们有信心完成我们的软件.我在网上搜了一些关于监听的 ...
- 通过机器学习的线性回归算法预测股票走势(用Python实现)
在本人的新书里,将通过股票案例讲述Python知识点,让大家在学习Python的同时还能掌握相关的股票知识,所谓一举两得.这里给出以线性回归算法预测股票的案例,以此讲述通过Python的sklearn ...
- 掌握git基本功
前言 最近想把代码传到GitHub上,结果我发现的demo的npm全是本地安装,上穿到GitHub要死要死,几百M,然后我就搜了下怎么不上传node_modules弄了半天也没成功,于是准备静下心学一 ...
- spring boot 中的路径映射
在spring boot中集成thymeleaf后,我们知道thymeleaf的默认的html的路径为classpath:/templates也就是resources/templates,那如何访问这 ...
- JavaScript中valueOf、toString的隐式调用
今天在群上有人问这样一个问题: 函数add可以实现连续的加法运算函数add语法如下add(num1)(num2)(num3)...;//注意这里是省略号哟,无限使用举例如下:add(10)(10)=2 ...
- OptimalSolution(2)--二叉树问题(1)遍历与查找问题
一.二叉树的按层打印与ZigZag打印 1.按层打印: 1 Level 1 : 1 / \ 2 3 Level 2 : 2 3 / / \ 4 5 6 Level 3 : 4 5 6 / \ 7 8 ...