1855: [Scoi2010]股票交易

Time Limit: 5 Sec  Memory Limit: 64 MB
Submit: 1083  Solved: 519
[Submit][Status][Discuss]

Description

最近lxhgww又迷上了投资股票,通过一段时间的观察和学习,他总结出了股票行情的一些规律。 通过一段时间的观察,lxhgww预测到了未来T天内某只股票的走势,第i天的股票买入价为每股APi,第i天的股票卖出价为每股BPi(数据保证对于每个i,都有APi>=BPi),但是每天不能无限制地交易,于是股票交易所规定第i天的一次买入至多只能购买ASi股,一次卖出至多只能卖出BSi股。 另外,股票交易所还制定了两个规定。为了避免大家疯狂交易,股票交易所规定在两次交易(某一天的买入或者卖出均算是一次交易)之间,至少要间隔W天,也就是说如果在第i天发生了交易,那么从第i+1天到第i+W天,均不能发生交易。同时,为了避免垄断,股票交易所还规定在任何时间,一个人的手里的股票数不能超过MaxP。 在第1天之前,lxhgww手里有一大笔钱(可以认为钱的数目无限),但是没有任何股票,当然,T天以后,lxhgww想要赚到最多的钱,聪明的程序员们,你们能帮助他吗?

Input

输入数据第一行包括3个整数,分别是T,MaxP,W。 接下来T行,第i行代表第i-1天的股票走势,每行4个整数,分别表示APi,BPi,ASi,BSi。

Output

输出数据为一行,包括1个数字,表示lxhgww能赚到的最多的钱数。

Sample Input

5 2 0
2 1 1 1
2 1 1 1
3 2 1 1
4 3 1 1
5 4 1 1

Sample Output

3

HINT

对于30%的数据,0 < =W 对于50%的数据,0 < =W 对于100%的数据,0 < =W 
对于所有的数据,1 < =BPi < =APi < =1000,1 < =ASi,BSi < =MaxP

Source

[Submit][Status][Discuss]

/*
方法:单调队列优化DP
设f[i][j]代表前i天有j份股票时的最大利润。
三种更新:
1.不交易:f[i][j]=max(f[i][j],f[i-1][j]);
2.买入:f[i][j]=max(f[i][j],f[i-w-1][k]-(j-k)*AP[i])(k>=j-AS[i]);
3.卖出:f[i][j]=max(f[i][j],f[i-w-1][k]+(k-j)*BP[i])(k<=max(maxp,j+BS[i]))
然后我们观察式子,第一种更新O(1)完成,
第二和第三的时候如果枚举k的话复杂度承受不了,所以考虑怎么优化,
显而易见第二三种是线性的,所以考虑到队列可不可行?
于是整理表达式,发现可行,则按照f[i-w-1][k]+k*AP[i]以及f[i-w-1][k]+k*BP[i]维护递减即可。
*/
#include<cstdio>
#include<cstring>
#include<iostream>
#define set(x) freopen(#x".in","r",stdin);freopen(#x".out","w",stdout);
using namespace std;
inline int read(){
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
const int N=;
int n,maxp,w,ans,AP[N],BP[N],AS[N],BS[N];
int f[N][N],q[N];
int main(){
set(trade)
n=read();maxp=read();w=read();
for(int i=;i<=n;i++) AP[i]=read(),BP[i]=read(),AS[i]=read(),BS[i]=read();
memset(f,-0x3f,sizeof f);
for(int i=;i<=n;i++){
for(int j=;j<=AS[i];j++) f[i][j]=-AP[i]*j;
for(int j=;j<=maxp;j++) f[i][j]=max(f[i][j],f[i-][j]);
int d=i-w-;
if(d>=){
int h=,t=;
for(int j=;j<=maxp;j++){
while(h<t&&q[h]<j-AS[i]) h++;
while(h<t&&f[d][j]+j*AP[i]>=f[d][q[t-]]+q[t-]*AP[i]) t--;
q[t++]=j;
if(h<t) f[i][j]=max(f[i][j],f[d][q[h]]-(j-q[h])*AP[i]);
}
h=,t=;
for(int j=maxp;j>=;j--){
while(h<t&&q[h]>j+BS[i]) h++;
while(h<t&&f[d][j]+j*BP[i]>=f[d][q[t-]]+q[t-]*BP[i]) t--;
q[t++]=j;
if(h<t) f[i][j]=max(f[i][j],f[d][q[h]]+(q[h]-j)*BP[i]);
}
}
}
for(int i=;i<=maxp;i++) ans=max(ans,f[n][i]);
printf("%d\n",ans);
return ;
}

思维导航

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int N=;
int n,maxp,w;
int ap[N],bp[N];
int as[N],bs[N];
inline int read(){
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}/*
int f[N][N][2];//30
//1/0 have traded or not
int dfs(int cur,int num,bool d){
int &res=f[cur][num][d];
if(~res) return res;
res=0;
if(cur>=n) return res;
for(int i=(d?cur+w+1:cur+1);i<=n;i++){
res=max(res,dfs(i,num,0));
for(int j=1;j<=(maxp-num,as[i]);j++){
res=max(res,dfs(i,num+j,1)-j*ap[i]);
}
for(int j=1;j<=min(num,bs[i]);j++){
res=max(res,dfs(i,num-j,1)+j*bp[i]);
}
}
return res;
}
//30
void fdp(){
for(int i=n-1,t;~i;i--){
for(int j=0;j<=maxp;j++){
for(int d=0;d<2;d++){
for(int k=(d?i+w+1:i+1);k<=n;k++){
int &res=f[i][j][d];
res=max(res,f[k][j][0]);
for(int h=1;h<=min(maxp-j,as[k]);h++){
res=max(res,f[k][j+h][1]-h*ap[k]);
}
for(int h=1;h<=min(j,bs[k]);h++){
res=max(res,f[k][j-h][1]+h*bp[k]);
}
}
}
}
}
printf("%d\n",f[0][0][0]);
}*/
//
int f[N][N];
void dp(){
for(int j=;j<=maxp;j++) f[n][j]=;
for(int i=n-;~i;i--){
for(int j=;j<=maxp;j++){
int &res=f[i][j];
for(int k=i+;k<=n;k++) res=max(res,f[k][j]);
for(int k=i+w+;k<=n;k++){
for(int h=;h<=min(maxp-j,as[k]);h++){
res=max(res,f[k][j+h]-h*ap[k]);
}
for(int h=;h<=min(j,bs[k]);h++){
res=max(res,f[k][j-h]+h*bp[k]);
}
}
}
}
printf("%d\n",f[][]);
}
//
void Dp(){
memset(f,-0x3f,sizeof f);
for(int i=;i<=n;i++){
for(int j=;j<=as[i];j++){
f[i][j]=-j*ap[i];
}
}
for(int i=;i<=n;i++){
for(int j=;j<=maxp;j++){
f[i][j]=max(f[i][j],f[i-][j]);
for(int k=;k<i-w;k++){
for(int h=max(j-as[i],);h<j;h++){
f[i][j]=max(f[i][j],f[k][h]-(j-h)*ap[i]);
}
for(int h=j+;h<=min(j+bs[i],maxp);h++){
f[i][j]=max(f[i][j],f[k][h]+(h-j)*bp[i]);
}
}
}
}
printf("%d\n",max(f[n][],));
}
//
int q[N];
void DP(){
memset(f,-0x3f,sizeof f);
for(int i=;i<=n;i++){
for(int j=;j<=as[i];j++){
f[i][j]=-j*ap[i];
}
}
for(int i=;i<=n;i++){
for(int j=;j<=maxp;j++) f[i][j]=max(f[i][j],f[i-][j]);
int d=i-w-;
if(d>=){
int h=,t=;
for(int j=;j<=maxp;j++){
while(h<t&&q[h]<j-as[i]) h++;
while(h<t&&f[d][j]+j*ap[i]>=f[d][q[t-]]+q[t-]*ap[i]) t--;
q[t++]=j;
if(h<t) f[i][j]=max(f[i][j],f[d][q[h]]-(j-q[h])*ap[i]);
}
h=,t=;
for(int j=maxp;j>=;j--){
while(h<t&&q[h]>j+bs[i]) h++;
while(h<t&&f[d][j]+j*bp[i]>=f[d][q[t-]]+q[t-]*bp[i]) t--;
q[t++]=j;
if(h<t) f[i][j]=max(f[i][j],f[d][q[h]]+(q[h]-j)*bp[i]);
}
}
}
printf("%d\n",max(f[n][],));
}
int main(){
n=read();maxp=read();w=read();
for(int i=;i<=n;i++) ap[i]=read(),bp[i]=read(),as[i]=read(),bs[i]=read();
// memset(f,-1,sizeof f);
// printf("%d\n",dfs(0,0,0));
// fdp();
// dp();
DP();
return ;
}

1855: [Scoi2010]股票交易[单调队列优化DP]的更多相关文章

  1. 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 ...

  2. 【bzoj1855】 [Scoi2010]股票交易 单调队列优化DP

    上一篇blog已经讲了单调队列与单调栈的用法,本篇将讲述如何借助单调队列优化dp. 我先丢一道题:bzoj1855 此题不难想出O(n^4)做法,我们用f[i][j]表示第i天手中持有j只股票时,所赚 ...

  3. 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 ...

  4. LUOGU P2569 [SCOI2010]股票交易(单调队列优化dp)

    传送门 解题思路 不难想一个\(O(n^3)\)的\(dp\),设\(f_{i,j}\)表示第\(i\)天,手上有\(j\)股的最大收益,因为这个\(dp\)具有单调性,所以\(f_i\)可以贪心的直 ...

  5. SCOI 股票交易 单调队列优化dp

    这道题 我很蒙.....首先依照搞单调队列优化dp的一般思路 先写出状态转移方程 在想法子去优化 这个题目中说道w就是这一天要是进行操作就是从前w-1天转移而来因为之前的w天不允许有操作!就是与这些天 ...

  6. BZOJ 1855 股票交易 - 单调队列优化dp

    传送门 题目分析: \(f[i][j]\)表示第i天,手中拥有j份股票的最优利润. 如果不买也不卖,那么\[f[i][j] = f[i-1][j]\] 如果买入,那么\[f[i][j] = max\{ ...

  7. BZOJ1855 股票交易 单调队列优化 DP

    描述 某位蒟佬要买股票, 他神奇地能够预测接下来 T 天的 每天的股票购买价格 ap, 股票出售价格 bp, 以及某日购买股票的上限 as,  某日出售股票上限 bs, 并且每次股票交 ♂ 易 ( 购 ...

  8. 股票交易——单调队列优化DP

    题目描述 思路 蒟蒻还是太弱了,,就想到半个方程就GG了,至于什么单调队列就更想不到了. $f[i][j]$表示第$i天有j$张股票的最大收益. 那么有四种选择: 不买股票:$f[i][j]=max( ...

  9. 2018.09.10 bzoj1855: [Scoi2010]股票交易(单调队列优化dp)

    传送门 单调队列优化dp好题. 有一个很明显的状态设置是f[i][j]表示前i天完剩下了j分股票的最优值. 显然f[i][j]可以从f[i-w-1][k]转移过来. 方程很好推啊. 对于j<kj ...

随机推荐

  1. 摘:LIB和DLL的区别与在VC中的使用

    共有两种库:一种是LIB包含了函数所在的DLL文件和文件中函数位置的信息(入口),代码由运行时加载在进程空间中的DLL提供,称为动态链接库dynamic link library.一种是LIB包含函数 ...

  2. 我使用过的Linux命令之clear - 清除终端屏幕,不是cls

    原文链接:http://codingstandards.iteye.com/blog/804213 用途说明 clear命令是用来清除终端屏幕的(clear the terminal screen), ...

  3. Lintcode---把排序树组转换为高度最小的二叉树

    给一个排序数组(从小到大),将其转换为一棵高度最小的排序二叉树. 注意事项 There may exist multiple valid solutions, return any of them. ...

  4. 转 多线程 闭锁(Latch) 栅栏(CyclicBarrier)

    java多线程并发系列之闭锁(Latch)和栅栏(CyclicBarrier) 标签: java并发编程 2015-05-28 16:45 2939人阅读 评论(0) 收藏 举报 本文章已收录于: . ...

  5. vue $http请求服务

    vue中的$http服务  需要引入一个叫vue-resource.js的文件,因为vue.js中没有$http服务.如果需要使用这个服务去百度下载vue-resource.js 然后引进项目即可. ...

  6. 带密匙的php加密解密代码

    php加密解密示例,代码如下: <?php $id = "http://www.jbxue.com"; $token = encrypt($id, 'E', 'jbxue') ...

  7. atitit.自动生成数据库结构脚本,或者更换数据库,基于hibernate4

    atitit.自动生成数据库结构脚本,或者更换数据库,基于hibernate4 目前近况:: 更换数据库,但是是使用spring集成的. <!-- hibernate配置文件路径 --> ...

  8. socket发送http请求

  9. CentOS6.2下安装配置MySql

    转自:Linux学习之CentOS(十三)--CentOS6.4下Mysql数据库的安装与配置 如果要在Linux上做j2ee开发,首先得搭建好j2ee的开发环境,包括了jdk.tomcat.ecli ...

  10. CM本地Yum源的搭建

    CM本地Yum源的搭建 以本地yum源安装CM5为例,解释本地yum源的安装和利用本地yum源安装CM5. Cloudera Manager 5(以下简称CM)默认采用在线安装的方式,给不能联互联网或 ...