第一个单调队列优化dp

写了半天,最后初始化搞错了还一直wa。。

题目大意:

炒股,总共 t 天,每天可以买入na[i]股,卖出nb[i]股,价钱分别为pa[i]和pb[i],最大同时拥有p股

且一次交易后至少要间隔w天才能再次交易,初始有0股,本金无限,求最大收益

题解:
dp[i][j]表示第 i 天,有 j 股的最大收益

状态转移 dp[i][j]=max{dp[i-1][j](不买不卖),dp[r][k]-(j-k)*pa[i](i-r>w,j-k<=na[i],买),dp[r][k]+(k-j)*pb[i](i-r>w,k-j<=nb[i],卖)}

复杂度 为 t*t*p*p

首先我们可以看出 dp[i][j]>=dp[i-1][j](不买不卖转移)

所以可以将 r 确定为 i-w-1,复杂度变为t*p*p 还是很大

然后对于买,移项有

dp[i][j]+j*pa[i]=dp[r][k]+k*pa[i]。右边与 j无关, 可见我们只需要对每一个 i 维护一个关于k的单调队列,就可以在 p时间内求出所有的dp[i][j]

复杂度降为 t*p 可以接受了

最后注意下边界条件:

1到w+1的都是从初始条件下转移的

代码:

#include <iostream>
#include <stdio.h>
#include<string.h>
#include<algorithm>
#include<string>
#include<ctype.h>
using namespace std;
#define MAXN 2000
#define inf 200000000
int na[MAXN+],nb[MAXN+],pa[MAXN+],pb[MAXN+];
int dp[MAXN+][MAXN+];
int t,p,w;
typedef struct Node
{
int val,num;
}node;
typedef struct dqueue
{
node q[MAXN*];
int l,r;
bool empty()
{
return l==r;
}
void clear()
{
l=;r=;
}
node front()
{
return q[l];
}
void pop()
{
l++;
}
void push(node x)
{
if(l==r)
{
q[r++]=x;
return;
}
if(x.val>q[l].val)
{
r=l;
q[r++]=x;
return;
}
for(int i=r;i>l;i--)
{
if(x.val<q[i-].val)
{
r=i;
break;
}
}
q[r++]=x;
}
}Dqueue;
Dqueue qa,qb;
int buy(int now,int n)
{
node tmp;
while()
{
tmp=qa.front();
if(tmp.num<n-na[now])
{
qa.pop();
}
else
break;
}
return tmp.val;
}
int sale(int now,int n)
{
node tmp;
while()
{
tmp=qb.front();
if(tmp.num<n)
{
qb.pop();
}
else
break;
}
return tmp.val;
}
void DP()
{
for(int i=;i<=t;i++)
{
for(int j=;j<=p;j++)
{
dp[i][j]=-inf;
}
}
node no;
for(int i=;i<=w+;i++)
{
for(int j=;j<=na[i];j++)
{
dp[i][j]=-pa[i]*j;
}
for(int j=;j<=p;j++)
{
dp[i][j]=max(dp[i][j],dp[i-][j]);
}
}
for(int i=w+;i<=t;i++)
{
qa.clear();
qb.clear();
int r=i-w-; //上一次交易的天数
for(int j=;j<nb[i];j++)
{
no.num=j;
no.val=dp[r][j]+j*pb[i];
qb.push(no);
}
for(int j=;j<=p;j++)
{
no.num=j;
no.val=dp[r][j]+j*pa[i];
qa.push(no);
if(j+nb[i]<=p)
{
no.num=j+nb[i];
no.val=dp[r][j+nb[i]]+(j+nb[i])*pb[i];
qb.push(no);
}
dp[i][j]=max(dp[i][j],dp[i-][j]); //不买
int tmp=buy(i,j);
dp[i][j]=max(dp[i][j],tmp-j*pa[i]); //买
tmp=sale(i,j);
dp[i][j]=max(dp[i][j],tmp-j*pb[i]); //卖
}
}
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d%d",&t,&p,&w);
for(int i=;i<=t;i++)
{
scanf("%d%d%d%d",pa+i,pb+i,na+i,nb+i);
}
DP();
int ans=;
for(int i=;i<=p;i++)
{
ans=max(ans,dp[t][i]);
}
printf("%d\n",ans);
}
return ;
}

hdu3401:单调队列优化dp的更多相关文章

  1. 单调队列优化DP,多重背包

    单调队列优化DP:http://www.cnblogs.com/ka200812/archive/2012/07/11/2585950.html 单调队列优化多重背包:http://blog.csdn ...

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

  3. Parade(单调队列优化dp)

    题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=2490 Parade Time Limit: 4000/2000 MS (Java/Others)    ...

  4. BZOJ_3831_[Poi2014]Little Bird_单调队列优化DP

    BZOJ_3831_[Poi2014]Little Bird_单调队列优化DP Description 有一排n棵树,第i棵树的高度是Di. MHY要从第一棵树到第n棵树去找他的妹子玩. 如果MHY在 ...

  5. 【单调队列优化dp】 分组

    [单调队列优化dp] 分组 >>>>题目 [题目] 给定一行n个非负整数,现在你可以选择其中若干个数,但不能有连续k个数被选择.你的任务是使得选出的数字的和最大 [输入格式] ...

  6. [小明打联盟][斜率/单调队列 优化dp][背包]

    链接:https://ac.nowcoder.com/acm/problem/14553来源:牛客网 题目描述 小明很喜欢打游戏,现在已知一个新英雄即将推出,他同样拥有四个技能,其中三个小技能的释放时 ...

  7. 单调队列以及单调队列优化DP

    单调队列定义: 其实单调队列就是一种队列内的元素有单调性的队列,因为其单调性所以经常会被用来维护区间最值或者降低DP的维数已达到降维来减少空间及时间的目的. 单调队列的一般应用: 1.维护区间最值 2 ...

  8. BZOJ1791[Ioi2008]Island 岛屿 ——基环森林直径和+单调队列优化DP+树形DP

    题目描述 你将要游览一个有N个岛屿的公园.从每一个岛i出发,只建造一座桥.桥的长度以Li表示.公园内总共有N座桥.尽管每座桥由一个岛连到另一个岛,但每座桥均可以双向行走.同时,每一对这样的岛屿,都有一 ...

  9. P4381 [IOI2008]Island(基环树+单调队列优化dp)

    P4381 [IOI2008]Island 题意:求图中所有基环树的直径和 我们对每棵基环树分别计算答案. 首先我们先bfs找环(dfs易爆栈) 蓝后我们处理直径 直径不在环上,就在环上某点的子树上 ...

随机推荐

  1. Linux内核数据包的发送传输

    本文主要讲解了Linux内核数据包的传输流程,使用的内核的版本是2.6.32.27 为了方便理解,本文采用整体流程图加伪代码的方式从内核高层面上梳理了二层数据包发送传输的流程,希望可以对大家有所帮助. ...

  2. Nyoj 43 24 Point game 【DFS】

    24 Point game 时间限制:3000 ms  |  内存限制:65535 KB 难度:5 描写叙述 There is a game which is called 24 Point game ...

  3. 【JavaScript】轻易改变的背景和字体颜色页面

    JavaScript,点击button改变页面背景和字体颜色,网页有N颜色的变化button.点击不同button,网页字体和背景将被改变为不同的颜色. 非常easy的JavaScript小程序. 一 ...

  4. HDU 1015 Safecracker 解决问题的方法

    Problem Description === Op tech briefing, 2002/11/02 06:42 CST ===  "The item is locked in a Kl ...

  5. linux查看文件大小df-du

    1.  显示目前所有文件系统的可用空间及使用情形,h表示使用 GB.MB 等易读的格式 [root@rusky ldap]# df -hFilesystem Size Used Avail Use% ...

  6. Javascript高级程序设计读书笔记(第10章 DOM)

    第10章 DOM 10.1  节点层次 每个节点都有一个nodeType属性,用于表明节点的类型.任何节点类型必是下面中的一个: Node.Element_NODE(1); NODE.ATTRIBUT ...

  7. CSS选择器列表

    h1 类型选择器 选择元素的一个类型 .className 类选择器 以class属性的值来选择元素,可以在一个页面中出现多个 #idName ID选择器 以id属性的值来选择元素,在页面中是唯一的, ...

  8. 转载——CLR标量函数、表值函数和聚合函数(UDA)

    本节主要介绍使用CLR创建标量函数,表值函数和聚合函数. 所谓标量函数指的就是此函数只返回一个值.表值函数返回值是一个表.聚合函数是在select语句中使用的,用来聚合一个结果集,类似于Sum()或是 ...

  9. Swift中可能失败的构造器的传播(调用)和重写

    import Foundation /* 可能失败构造器的传播(调用) 1.可能失败的构造器可以调用同一个类中的普通构造器 2.普通构造器不能调用同一个类中的可能失败构造器 3.结构体中, 普通构造器 ...

  10. C# winform DataTable 批量数据处理 增、删、改 .

    1.批量新增,采用高效的SqlBulkCopy SqlBulkCopy DTS = new System.Data.SqlClient.SqlBulkCopy(con); DTS.NotifyAfte ...