1855: [Scoi2010]股票交易[单调队列优化DP]
1855: [Scoi2010]股票交易
Time Limit: 5 Sec Memory Limit: 64 MB
Submit: 1083 Solved: 519
[Submit][Status][Discuss]
Description
Input
Output
Sample Input
2 1 1 1
2 1 1 1
3 2 1 1
4 3 1 1
5 4 1 1
Sample Output
HINT
对于30%的数据,0 < =W 对于50%的数据,0 < =W 对于100%的数据,0 < =W
对于所有的数据,1 < =BPi < =APi < =1000,1 < =ASi,BSi < =MaxP
Source
/*
方法:单调队列优化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]的更多相关文章
- 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只股票时,所赚 ...
- 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\)可以贪心的直 ...
- SCOI 股票交易 单调队列优化dp
这道题 我很蒙.....首先依照搞单调队列优化dp的一般思路 先写出状态转移方程 在想法子去优化 这个题目中说道w就是这一天要是进行操作就是从前w-1天转移而来因为之前的w天不允许有操作!就是与这些天 ...
- 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, 并且每次股票交 ♂ 易 ( 购 ...
- 股票交易——单调队列优化DP
题目描述 思路 蒟蒻还是太弱了,,就想到半个方程就GG了,至于什么单调队列就更想不到了. $f[i][j]$表示第$i天有j$张股票的最大收益. 那么有四种选择: 不买股票:$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 ...
随机推荐
- C# BackgroundWorker的Bug???
废话不多说,上代码: public partial class Form1 : Form { BackgroundWorker _bgWorker; int count; public Form1() ...
- DevExpress实现GridControl删除所有行的方法
/// <summary> /// 删除全部行 /// </summary> /// <param name="gridView">GridVi ...
- java中成员变量、代码块、构造函数运行顺序
1.java虚拟机执行程序,首先须要装载类,安装现装载父类,初始化父类的静态代码块和静态成员变量 再load子类. 初始化子类静态代码块和成员变量 2.load完成父类与子类后,从main函数入口运行 ...
- MySQL中的Multi-Range Read优化
MySQL 5.6开始支持Multi-Range Read(MRR)优化.目的是味儿减少磁盘的随机访问,并且将随机访问转化为较为顺序的数据访问,这对IO-bound类型的SQL查询语句可带来性能极大的 ...
- 电影大全 API接口
http://www.apix.cn/services/show/29 http://www.apix.cn/services/show/112
- HDU 2844 Coin 多重背包
Coins Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submi ...
- locatin
//location对象 //初始url:http://www.wrox.com/WileyCDA: //将URL修改为:http://www.wrox.com/WileyCDA/#section1 ...
- 设置root密码,su与sudo的区别
sudo passwd root 可以修改root密码,但首先会要求你输入当前用户的密码 sudo的意思是switch user do,默认切换到root,要求当前用户的密码,会自动调用exit返回到 ...
- Vue 状态管理
类flux状态管理的官方实现 由于多个状态分散的跨越在许多组件和交互间的各个角落,大型应用复杂度也经常逐渐增长. 为了解决这个问题,vue提供了vuex:我们有收到elm启发的状态管理库,vuex甚至 ...
- CEF Xilium.CefGlue 在当前窗体中打开全部链接(防止弹窗)
我们在使用Xilium.CefGlue编写浏览器应用程序时.对于嵌入的网页假设有链接会在新窗体打开.这种用户体验会非常差.因此我们须要改动程序,使全部链接都在当前窗体中打开. 首先引用Xilium.C ...