//只能写出裸的动规,为什么会有人能想到用单调队列优化Orz

题目描述

最近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

题解:

裸的方程:

令每行四个数a,b,c,d

方程f[i][j]表示第 i 天结束后,手里剩下 j 股的最大利润
则 不买不卖:f[i][j]=f[i-1][j]
买入: f[i][j]=max{f[i-w-1][k]-a[i]*(j-k)}(j-c[i]<=k<=j-1)
卖出: f[i][j]=max{f[i-w-1][k]+b[i]*(k-j)}(j+1<=k<=j+d[i])

正确的方法(迷之变形):

买入:f[i][j]=max{f[i-w-1][k]+k*a[i]}-a[i]*j
卖出:f[i][j]=max{f[i-w-1][k]+k*b[i]}-b[i]*j
所以可以将括号里面的方程式压入单调队列

此时复杂度降低为复杂度O(N*W)原来O(N*W*2)

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define man 2010
int a[man],b[man],c[man],d[man],f[man][man],sta[man];
int t,mp,w,hd,tl;
int main()
{
cin>>t>>mp>>w;
for(int i=;i<=t;i++) cin>>a[i]>>b[i]>>c[i]>>d[i];
memset(f,-/,sizeof(f));
for(int i=;i<=t;i++)f[i][]=;
for(int i=;i<=t;i++)
{
for(int j=;j<=c[i];j++)f[i][j]=-a[i]*j;
for(int j=mp;j>=;j--)f[i][j]=max(f[i][j],f[i-][j]);
if(i-w->=)
{
hd=;tl=;
for(int j=;j<=mp;j++)
{
while(hd<=tl&&sta[hd]<j-c[i])hd++;
while(hd<=tl&&f[i-w-][j]+a[i]*j>=f[i-w-][sta[tl]]+a[i]*sta[tl])tl--;
sta[++tl]=j;
if(hd<=tl)
f[i][j]=max(f[i][j],f[i-w-][sta[hd]]-a[i]*(j-sta[hd]));
}
hd=;tl=;
for(int j=mp;j>=;j--)
{
while(hd<=tl&&sta[hd]>j+d[i])hd++;
while(hd<=tl&&f[i-w-][j]+b[i]*j>=f[i-w-][sta[tl]]+b[i]*sta[tl])tl--;
sta[++tl]=j;
if(hd<=tl)
f[i][j]=max(f[i][j],f[i-w-][sta[hd]]+b[i]*(sta[hd]-j));
}
}
}
int ans=;
for(int i=;i<=mp;i++)ans=max(ans,f[t][i]);
cout<<ans<<endl;
}

话说,为什么大家的题解几乎都是一样的。。(我也是看别人的。。。)

最新文章

  1. Androide SQLiteDatabase数据库操作(转)
  2. 无法在Web服务器上启动调试,已附加了一个调试器
  3. Flume的安装与配置
  4. Some Skills in Visual Studio
  5. dedeCMS安装,前端样式不显示
  6. bash下自动重新运行git/curl等工具
  7. Socket 学习(三)
  8. 分享到JavaScript
  9. alpha-咸鱼冲刺day7
  10. [HAOI 2011]向量
  11. 链表详解(C语言)
  12. Xgboost GPU 加速
  13. Java基于opencv实现图像数字识别(五)—腐蚀、膨胀处理
  14. python 打印到控制台变颜色
  15. 基于【磁盘】操作的IO接口:File
  16. ubuntu安装虚拟环境
  17. ABAP WB01 BDC ”No batch input data for screen & &“ ”没有屏幕 & & 的批输入数据“
  18. pacbio bax.h5文件处理及ccs计算
  19. for...in的改进版for...of
  20. drf2 FBV和CBV

热门文章

  1. JSONUtils的几个常用方法
  2. C++直接初始化和复制初始化1
  3. Linux c- libevent
  4. Timesten 日常管理命令合集
  5. ThinkPHP Http工具类(用于远程采集 远程下载) phpSimpleHtmlDom采集类库_Jquery筛选方式 使用phpQuery轻松采集网页内容http://www.thinkphp.cn/extend/541.html
  6. 022:SQL优化--JOIN算法
  7. 第十章 Secret &amp; Configmap(下)
  8. python学习 (三十一) python中的class
  9. node连接mongoDB篇
  10. 构建:vue项目配置后端接口服务信息