【BZOJ1855】股票交易(动态规划,单调队列)
【BZOJ1855】股票交易(动态规划,单调队列)
题面
题解
很显然,状态之和天数以及当天剩余的股票数有关
设\(f[i][j]\)表示第\(i\)天进行了交易,剩余股票数为\(j\)的最大获利
每次枚举可以转移过来的天数以及股票数
再枚举买入或者卖出的数量,
时间复杂度\(O(T^2Mp^2)\),30pts(但是有40pts。。。)
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define ll long long
#define RG register
#define MAX 2222
inline int read()
{
RG int x=0,t=1;RG char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=-1,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return x*t;
}
int T,Mp,W;
int f[MAX][MAX];
int vb[MAX],vs[MAX],lb[MAX],ls[MAX];
int main()
{
T=read();Mp=read();W=read();
for(int i=1;i<=T;++i)
{
vb[i]=read();vs[i]=read();
lb[i]=read();ls[i]=read();
}
memset(f,-63,sizeof(f));
f[0][0]=0;
for(int i=1;i<=T;++i)
{
for(int j=0;j<=max(i-W-1,0);++j)
{
for(int k=0;k<=Mp;++k)
{
for(int l=1;k+l<=Mp&&l<=lb[i];++l)
f[i][k+l]=max(f[i][k+l],f[j][k]-l*vb[i]);
for(int l=1;l<=k&&l<=ls[i];++l)
if(l<=k)f[i][k-l]=max(f[i][k-l],f[j][k]+l*vs[i]);
}
}
}
int ans=0;
for(int i=1;i<=T;++i)ans=max(ans,f[i][0]);
printf("%d\n",ans);
return 0;
}
其实没有任何必要枚举可以转移过来的天数
把状态稍微改变一下
设\(f[i][j]\)表示第\(i\)天拥有的股票数为\(j\)的最大获利
每次可以从\(f[i-1]\)转移过来
这样只需要枚举交易的限制天数前就行了
复杂度\(O(TMp^2)\),50pts
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define ll long long
#define RG register
#define MAX 2222
inline int read()
{
RG int x=0,t=1;RG char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=-1,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return x*t;
}
int T,Mp,W;
int f[MAX][MAX];
int vb[MAX],vs[MAX],lb[MAX],ls[MAX];
int main()
{
T=read();Mp=read();W=read();
for(int i=1;i<=T;++i)
{
vb[i]=read();vs[i]=read();
lb[i]=read();ls[i]=read();
}
memset(f,-63,sizeof(f));
int ttt=f[0][0];
f[0][0]=0;
for(int i=1;i<=T;++i)
{
int j=max(0,i-W-1);
for(int k=0;k<=Mp;++k)
{
f[i][k]=max(f[i][k],f[i-1][k]);
for(int l=1;k+l<=Mp&&l<=lb[i];++l)
f[i][k+l]=max(f[i][k+l],f[j][k]-l*vb[i]);
for(int l=1;l<=k&&l<=ls[i];++l)
if(l<=k)f[i][k-l]=max(f[i][k-l],f[j][k]+l*vs[i]);
}
}
printf("%d\n",f[T][0]);
return 0;
}
听说数据比较水,50pts稍微优化一下可以卡过70pts
70pts:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define ll long long
#define RG register
#define MAX 2222
inline int read()
{
RG int x=0,t=1;RG char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=-1,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return x*t;
}
int T,Mp,W;
int f[MAX][MAX];
int vb[MAX],vs[MAX],lb[MAX],ls[MAX];
int main()
{
T=read();Mp=read();W=read();
for(int i=1;i<=T;++i)
{
vb[i]=read();vs[i]=read();
lb[i]=read();ls[i]=read();
}
memset(f,-63,sizeof(f));
f[0][0]=0;
for(int i=1;i<=T;++i)
{
for(int j=0;j<=lb[i];++j)f[i][j]=-j*vb[i];
for(int j=0;j<=Mp;++j)f[i][j]=max(f[i][j],f[i-1][j]);
if(i<=W)continue;
int j=i-W-1;
for(int k=0;k<=Mp;++k)
{
for(int l=1;k+l<=Mp&&l<=lb[i];++l)
f[i][k+l]=max(f[i][k+l],f[j][k]-l*vb[i]);
for(int l=1;l<=k&&l<=ls[i];++l)
if(l<=k)f[i][k-l]=max(f[i][k-l],f[j][k]+l*vs[i]);
}
}
printf("%d\n",f[T][0]);
return 0;
}
这个复杂度已经跑不了了
怎么解决转移的复杂度问题?
对于从\(W\)天(第\(x\)天)前购买/出售的转移
我们额外看看:
\(f[i][j]=max(f[x][k]+k*V-j*V)\)
貌似和\(j\)没什么关系诶
\(f[i][j]=max(f[x][k]+k*V)-j*V\)
这样就可以单调队列优化转移了
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define ll long long
#define RG register
#define MAX 2222
inline int read()
{
RG int x=0,t=1;RG char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=-1,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return x*t;
}
int T,Mp,W;
int f[MAX][MAX];
int vb[MAX],vs[MAX],lb[MAX],ls[MAX];
int l,r,Q[MAX];
int main()
{
T=read();Mp=read();W=read();
for(int i=1;i<=T;++i)
{
vb[i]=read();vs[i]=read();
lb[i]=read();ls[i]=read();
}
memset(f,-63,sizeof(f));
f[0][0]=0;
for(int i=1;i<=T;++i)
{
for(int j=0;j<=lb[i];++j)f[i][j]=-j*vb[i];
for(int j=0;j<=Mp;++j)f[i][j]=max(f[i][j],f[i-1][j]);
if(i<=W)continue;
int x=i-W-1,h,t;
h=1,t=0;
for(int j=0;j<=Mp;++j)
{
while(h<=t&&Q[h]<j-lb[i])++h;
while(h<=t&&f[x][Q[t]]+Q[t]*vb[i]<=f[x][j]+j*vb[i])--t;
Q[++t]=j;
if(h<=t)f[i][j]=max(f[i][j],f[x][Q[h]]+Q[h]*vb[i]-j*vb[i]);
}
h=1,t=0;
for(int j=Mp;j>=0;--j)
{
while(h<=t&&Q[h]>j+ls[i])++h;
while(h<=t&&f[x][Q[t]]+Q[t]*vs[i]<=f[x][j]+j*vs[i])--t;
Q[++t]=j;
if(h<=t)f[i][j]=max(f[i][j],f[x][Q[h]]+Q[h]*vs[i]-j*vs[i]);
}
}
printf("%d\n",f[T][0]);
return 0;
}
【BZOJ1855】股票交易(动态规划,单调队列)的更多相关文章
- 【BZOJ1855】[Scoi2010]股票交易 DP+单调队列
[BZOJ1855][Scoi2010]股票交易 Description 最近lxhgww又迷上了投资股票,通过一段时间的观察和学习,他总结出了股票行情的一些规律. 通过一段时间的观察,lxhgww预 ...
- BZOJ1855 [Scoi2010]股票交易 【单调队列优化dp】
题目链接 BZOJ1855 题解 设\(f[i][j]\)表示第\(i\)天结束时拥有\(j\)张股票时的最大收益 若\(i \le W\),显然在这之前不可能有交易 \[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 ...
- 洛谷P2569 (BZOJ1855)[SCOI2010]股票交易 【单调队列优化DP】
Description 最近lxhgww又迷上了投资股票,通过一段时间的观察和学习,他总结出了股票行情的一些规律. 通过一段时间的观察,lxhgww预测到了未来T天内某只股票的走势,第i天的股票买入价 ...
- 股票交易 (单调队列优化DP)
股票交易 $ solution: $ 这道题以前就写了,题目很好,但自己没有发题解,来补一篇: 首先,题目出得很有迷惑性,但我们不难想到状态要设天数,和自己手上的股票数目(因为这两个就是充要信息).而 ...
- P2569 [SCOI2010]股票交易 dp 单调队列优化
LINK:股票交易 题目确实不算难 但是坑点挺多 关于初值的处理问题我就wa了两次. 所以来谢罪. 由于在手中的邮票的数量存在限制 且每次买入卖出也有限制. 必然要多开一维来存每天的邮票数量. 那么容 ...
- BZOJ 1855 股票交易(单调队列优化DP)
题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1855 题意:最近lxhgww又迷上了投资股票, 通过一段时间的观察和学习,他总结出了股票 ...
- BZOJ_1096_[ZJOI2007]_仓库建设_(斜率优化动态规划+单调队列+特殊的前缀和技巧)
描述 http://www.lydsy.com/JudgeOnline/problem.php?id=1096 有\(n\)个工厂,给出第\(i\)个工厂的到1号工厂的距离\(x[i]\),货物数量\ ...
- BZOJ_1010_[HNOI2008]_玩具装箱toy_(斜率优化动态规划+单调队列)
描述 http://www.lydsy.com/JudgeOnline/problem.php?id=1010 给出\(n\)和\(l\).有\(n\)个玩具,第\(i\)个玩具的长度是\(c[i]\ ...
- UOJ#172. 【WC2016】论战捆竹竿 字符串 KMP 动态规划 单调队列 背包
原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ172.html 题解 首先,这个问题显然是个背包问题. 然后,可以证明:一个字符串的 border 长度可 ...
随机推荐
- Java多线程应用总结
一.基本方法 进程和线程一样,都是实现并发的一个基本单位.线程是比进程更小的执行单位,线程是在进程的基础上进行的进一步划分.所谓多线程,是指一个进程在执行过程中可以产生多个更小的程序单元,这些更小的单 ...
- Apache、Lighttpd、Nginx 三种web服务器对比
简介 1. Apache Apache是世界使用排名第一的Web服务器软件.它可以运行在几乎所有广泛使用的计算机平台上,由于其跨平台和安全性被广泛使用,是最流行的Web服务器端软件之一.Apac ...
- Linux下配置SNAT上网
局域网有一台主机A,没有公网的IP, 也就是没有办法直接连到互联网上下载东西,同时内网有另外一台主机B,有公网接入.这个时候为了让A连接到互联网,我把B设置成NAT主机,A的网关指向B.准确的来说,现 ...
- VirtualDOM与diff(Vue实现)
写在前面 因为对Vue.js很感兴趣,而且平时工作的技术栈也是Vue.js,这几个月花了些时间研究学习了一下Vue.js源码,并做了总结与输出.文章的原地址:https://github.com/an ...
- 存个emacs配置
emacs配置 (global-set-key [f9] 'compile-file) (global-set-key [f10] 'gud-gdb) (global-set-key (kbd &qu ...
- angular4升级angular5问题记录之No NgModule metadata found for 'AppModule'
在将项目从angular4升级到angular5的过程中,出现No NgModule metadata found for 'AppModule'问题,网上查找答案将app.module.ts进行再次 ...
- FFMpeg for PHP
PHP使用FFMpeg来转换视频格式.Github上搜索FFMPEG,到https://github.com/PHP-FFMpeg/PHP-FFMpeg. For Windows users : Pl ...
- Angular:利用内容投射向组件输入ngForOf模板
现在,我们写一个组件puppiesListCmp,用于显示小狗狗的列表: //puppies-list.component.ts @Component({ selector: 'puppies-lis ...
- Python 练习册,每天一个小程序----第0000题
题目 第 0000 题: 将你的 QQ 头像(或者微博头像)右上角加上红色的数字,类似于微信未读信息数量那种提示效果. 类似于图中效果 Code: from PIL import Image,Imag ...
- chrome使用Timeline做性能分析
使用Timeline做性能分析 Timeline面板记录和分析了web应用运行时的所有活动情况,这是研究和查找性能问题的最佳途径.###Timeline面板概览 Timeline面板主要有三个部分构成 ...