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. centos7 配置PPTP、L2TP、IPSec服务

    首先,推荐跑下面的脚本: https://github.com/BoizZ/PPTP-L2TP-IPSec-VPN-auto-installation-script-for-CentOS-7 这个脚本 ...

  2. php调试函数

    void debug_print_backtrace ([ int $options = 0 [, int $limit = 0 ]] ) array debug_backtrace ([ int $ ...

  3. ubuntu下修改读写权限

    把home下所有文件所有者改成输入目标 $ chown - R [your name].users /home/

  4. Linux系统(Ubuntu/Debian/RedHat/CentOS)超级简单的samba配置文件smb.conf

    1.超简单的smb.conf 该配置文件对Ubuntu和CentOS都好用. #============== Global Settings ============== [global] ## Br ...

  5. Makefile 8——使用依赖关系文件

    Makefile中存在一个include指令,它的作用如同C语言中的#include预处理指令.在Makefile中,可以通过include指令将自动生成的依赖关系文件包含进来,从而使得依赖关系文件中 ...

  6. a标签去掉下划线

    转载自:http://jingyan.baidu.com/article/a17d52853095838099c8f24e.html <a>是默认有下划线的.所以有时候为了美观,我们需要去 ...

  7. 示例 - 如何在ASP.NET中应用Spider Studio生成的DLL?

    >> 接前文 "示例 - 如何在Console应用程序中应用SpiderStudio生成的DLL?", 将其运用到ASP.NET中: 1. 创建WebApplicati ...

  8. winxp退市是微软windows操作系统的滑铁卢

    winxp退市是微软windows操作系统的滑铁卢 兵败如山倒,windowsxp退市.宣布微软时代结束,windows将逐步退出中国市场,取而代之将是中国人自己的操作系统.中国人努力.中国人加油,不 ...

  9. go web框架推荐

    https://blog.usejournal.com/top-6-web-frameworks-for-go-as-of-2017-23270e059c4b https://www.zhihu.co ...

  10. 数论 - 119. Magic Pairs

    Magic Pairs Problem's Link Mean: 已知N.A0.B0,对于给定X.Y,若A0X+B0Y能被N整除,则AX+BY也能被N整除,求所有的A.B.(0<=A.B< ...