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 ...
随机推荐
- 快速排序以及第k小元素的线性选择算法
简要介绍下快速排序的思想:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此 ...
- GraphicsMagick 学习笔记
两种最常用的图片处理工具:GraphicsMagick 或 ImageMagick,GM是IM的分支,这两个图片处理工具功能基本相同,各有特色.但他们并不是nodejs的插件,它们都是客户端软件,li ...
- Python 爬虫实例(6)—— 爬取蚂蚁免费代理
数据库表sql语句: CREATE TABLE `free_ip` ( `free_ip_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键', `ip` ...
- 编译安装PHP7并安装Redis扩展Swoole扩展(未实验)
用PECL自动安装Redis扩展.Swoole扩展 pecl install redis pecl install swool 编译安装PHP7并安装Redis扩展Swoole扩展 在编译php7的机 ...
- Spring Boot构建RESTful API
@Controller:修饰class,用来创建处理http请求的对象 @RestController:Spring4之后加入的注解,原来在@Controller中返回json需要@ResponseB ...
- 【转】Appium_API(翻译+用法说明)
转自:https://testerhome.com/topics/3711 1.contextscontexts(self): Returns the contexts within the curr ...
- shell获取用户输入
主题: 再学shell之获取用户输入echo -n(不换行)和read命令-p(提示语句) -n(字符个数) -t(等待时间) -s(不回显) 和“读文件”深入学习 1.基本读取read命令接收标准输 ...
- 信号处理函数(2)-sigismember()
定义: int sigismember(const sigset_t *set,int signum); 表头文件: #include<signal.h> 说明: sigismem ...
- dubbo异步调用三种方式
异步通讯对于服务端响应时间较长的方法是必须的,能够有效地利用客户端的资源,在dubbo中,消费端<dubbp:method>通过 async="true"标识. < ...
- 0073 javacTask: 源发行版 1.8 需要目标发行版 1.8
今天在编译执行下面这段代码的时候,编译报错:javacTask: 源发行版 1.8 需要目标发行版 1.8 public class Test { public static void main(St ...