题目描述

最近 \text{lxhgww}lxhgww 又迷上了投资股票,通过一段时间的观察和学习,他总结出了股票行情的一些规律。

通过一段时间的观察,\text{lxhgww}lxhgww 预测到了未来 TT 天内某只股票的走势,第 ii 天的股票买入价为每股 AP_iAPi​,第 ii 天的股票卖出价为每股 BP_iBPi​(数据保证对于每个 ii,都有 AP_i \geq BP_iAPi​≥BPi​),但是每天不能无限制地交易,于是股票交易所规定第 ii 天的一次买入至多只能购买 AS_iASi​ 股,一次卖出至多只能卖出 BS_iBSi​ 股。

另外,股票交易所还制定了两个规定。为了避免大家疯狂交易,股票交易所规定在两次交易(某一天的买入或者卖出均算是一次交易)之间,至少要间隔 WW 天,也就是说如果在第 ii 天发生了交易,那么从第 i+1i+1 天到第 i+Wi+W 天,均不能发生交易。同时,为了避免垄断,股票交易所还规定在任何时间,一个人的手里的股票数不能超过 \text{MaxP}MaxP。

在第 11 天之前,\text{lxhgww}lxhgww 手里有一大笔钱(可以认为钱的数目无限),但是没有任何股票,当然,TT 天以后,\text{lxhgww}lxhgww 想要赚到最多的钱,聪明的程序员们,你们能帮助他吗?

输入输出格式

输入格式:

输入数据第一行包括 33 个整数,分别是 TT,\text{MaxP}MaxP,WW。

接下来 TT 行,第 ii 行代表第 i-1i−1 天的股票走势,每行 44 个整数,分别表示 AP_i,\ BP_i,\ AS_i,\ BS_iAPi​, BPi​, ASi​, BSi​。

输出格式:

输出数据为一行,包括 11 个数字,表示 \text{lxhgww}lxhgww 能赚到的最多的钱数。

输入输出样例

输入样例#1: 复制

5 2 0
2 1 1 1
2 1 1 1
3 2 1 1
4 3 1 1
5 4 1 1
输出样例#1: 复制

3

说明

对于 30\%30% 的数据,0\leq W<T\leq 50,1\leq\text{MaxP}\leq500≤W<T≤50,1≤MaxP≤50

对于 50\%50% 的数据,0\leq W<T\leq 2000,1\leq\text{MaxP}\leq500≤W<T≤2000,1≤MaxP≤50

对于 100\%100% 的数据,0\leq W<T\leq 2000,1\leq\text{MaxP}\leq20000≤W<T≤2000,1≤MaxP≤2000

对于所有的数据,1\leq BP_i\leq AP_i\leq 1000,1\leq AS_i,BS_i\leq\text{MaxP}1≤BPi​≤APi​≤1000,1≤ASi​,BSi​≤MaxP

题意:

一共t天,最多可以持有maxp支股票。给定每天股票买入卖出价格和每天的交易限额。问可以最多赚多少钱。

思路:

应该能够想得到这是一个dp。子结构就是前i天能赚取的最多价格,这就是“阶段”,也就是第一维。同时我们还需要记录一下持有的股票数,因为状态转移时,不同的股票数的转移是不同的。

因此,dp[i][j]表示第i天持有j的时候所能赚取的最大值。

对于每一天我们都有三种情况。

1.不买也不卖。 那么转移方程就是

2.买入。买入有分两种情况,一种是之前什么都没有,这j股都是在第i天买的。

  另一种是之前的某一天买了k股,今天买了j-k股。而且题目要求两个交易的日子要间隔w天。

3.卖出。之前的某一天有k股,卖掉了k-j股,第i天剩下j股。

但是我们会发现状态转移的时候如果枚举k,会出现O(n^3)的复杂度,需要进一步优化。

观察状态转移方程我们可以把k合并同类项,比如卖出的式子可以变成

由于max{}中的是一个正数,假设我们设在j时这个值为x,扩展到j+1时,我们只有可能取x或者k=j时的值。他是一个递增的选择。

就可以用单调队列来维护这个值了。

由于卖出是由比j大的k推出的,所以在转移卖出这种情况的时候,j应该是逆序的。

 #include <iostream>
#include <set>
#include <cmath>
#include <stdio.h>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
#define inf 0x7f7f7f7f const int maxn = ;
int t, maxp, w;
struct node{
int ap, bp, as, bs;
}day[maxn];
int dp[maxn][maxn], que[maxn]; int main()
{
scanf("%d%d%d", &t, &maxp, &w);
memset(dp, -inf, sizeof(dp));
for(int i = ; i <= t; i++){
scanf("%d%d%d%d", &day[i].ap, &day[i].bp, &day[i].as, &day[i].bs);
}
for(int i = ; i <= t; i++){
for(int j = ; j <= day[i].as; j++){
dp[i][j] = -j * day[i].ap;
}
for(int j = ; j <= maxp; j++){
dp[i][j] = max(dp[i][j], dp[i - ][j]);
}
if(i <= w)continue;
int head = , tail = ;
for(int j = ; j <= maxp; j++){
while(dp[i - w - ][que[tail]] + que[tail] * day[i].ap <= dp[i - - w][j] + j * day[i].ap && head <= tail){
tail--;
}
que[++tail] = j;
while(j - que[head] > day[i].as){
head++;
}
dp[i][j] = max(dp[i][j], dp[i - w - ][que[head]] - (j - que[head]) * day[i].ap);
} head = , tail = ;
for(int j = maxp; j >= ; j--){
while(dp[i - w - ][que[tail]] + que[tail] * day[i].bp <= dp[i - - w][j] + j * day[i].bp && head <= tail){
tail--;
}
que[++tail] = j;
while(que[head] - j > day[i].bs){
head++;
}
dp[i][j] = max(dp[i][j], dp[i - - w][que[head]] + (que[head] - j) * day[i].bp);
}
} int ans = -;
for(int j = ; j <= maxp; j++){
ans = max(ans, dp[t][j]);
}
printf("%d\n", ans);
return ;
}

洛谷P2569 股票交易【dp】【单调队列】的更多相关文章

  1. 洛谷P2569 股票交易 [SCOI2010] dp

    正解:dp+单调队列优化 解题报告: 先放个传送门鸭qwq umm首先dp转移挺好想的?就买和不买 f[i][j]表示第i天手上有j的股份的最多钱,转移也很好想?就枚举第1天到第i-w-1天枚举买k股 ...

  2. 【Luogu】P2569股票交易(单调队列优化DP)

    题目链接 首先这题可以肯定的是朴素DP秒出.然后单调队列优化因为没接触过所以不会emmm 而且脑补没补出来 坐等四月省选倒数第一emmm 心态爆炸,偷懒放题解链接 #include<cstdio ...

  3. P2569 [SCOI2010]股票交易 dp 单调队列优化

    LINK:股票交易 题目确实不算难 但是坑点挺多 关于初值的处理问题我就wa了两次. 所以来谢罪. 由于在手中的邮票的数量存在限制 且每次买入卖出也有限制. 必然要多开一维来存每天的邮票数量. 那么容 ...

  4. 洛谷P2569 股票交易

    题目传送门https://www.luogu.org/problemnew/show/P2569 第一眼看题就觉得是个dp ,然后看到2000的范围,hmm大概是个n^2的2维dp 开始设状态,第一维 ...

  5. 洛谷P1776--宝物筛选(单调队列+多重背包)

    https://www.luogu.org/problemnew/show/P1776 单调队列+多重背包的讲解https://www.cnblogs.com/JoeFan/p/4165956.htm ...

  6. 【洛谷】【动态规划+单调队列】P1714 切蛋糕

    [题目描述:] 今天是小Z的生日,同学们为他带来了一块蛋糕.这块蛋糕是一个长方体,被用不同色彩分成了N个相同的小块,每小块都有对应的幸运值. 小Z作为寿星,自然希望吃到的第一块蛋糕的幸运值总和最大,但 ...

  7. 【洛谷】【动态规划+单调队列】P1725 琪露诺

    [题目描述:] 在幻想乡,琪露诺是以笨蛋闻名的冰之妖精. 某一天,琪露诺又在玩速冻青蛙,就是用冰把青蛙瞬间冻起来.但是这只青蛙比以往的要聪明许多,在琪露诺来之前就已经跑到了河的对岸.于是琪露诺决定到河 ...

  8. 【BZOJ1855】[Scoi2010]股票交易 DP+单调队列

    [BZOJ1855][Scoi2010]股票交易 Description 最近lxhgww又迷上了投资股票,通过一段时间的观察和学习,他总结出了股票行情的一些规律. 通过一段时间的观察,lxhgww预 ...

  9. 洛谷luogu3957跳房子(单调队列优化)

    QwQ被普及组的题折磨的死去活来. 硬是卡线段树,没卡过QwQ oi生涯,第一道正经的单调队列dp题 进入正题 题目大意: 其中\(n \le 500000\) 看到这个题的第一感觉就是二分金币数 很 ...

随机推荐

  1. Strict Mode (JavaScript)

    摘要: ECMAScript5中引入的严格模式,通过让JavaScript运行环境对一些开发过程中最常见和不易发现的错误做出和当前不同的处理,来让开发者拥有一个”更好”的JavaScript语言.但目 ...

  2. flume配置文件

    读文件log传入kafka中 agent.sources = s1 agent.channels = c1 agent.sinks = k1 agent.sources.s1.type=exec ag ...

  3. Ubuntu14.04下Mongodb(离线安装方式|非apt-get)安装部署步骤(图文详解)(博主推荐)

    不多说,直接上干货! 说在前面的话  首先,查看下你的操作系统的版本. root@zhouls-virtual-machine:~# cat /etc/issue Ubuntu LTS \n \l r ...

  4. SPREAD for Windows Forms 代码片段

    'スクロールバーの移動 FpSpread1.ShowColumn(, , HorizontalPosition.Left) 'SetActiveCellの後.LeaveCellを呼び出す Dim ss ...

  5. Python中的类(上)

    在Python中,可以通过class关键字定义自己的类,然后通过自定义的类对象类创建实例对象. 例如,下面创建了一个Student的类,并且实现了这个类的初始化函数"__init__&quo ...

  6. ios开发之--通过通知监听textfield的输入状态,判断按钮的状态

    第一步: _rightBtn = [UIButton buttonWithType:UIButtonTypeCustom]; _rightBtn.frame = CGRectMake(kWidth - ...

  7. [C] 如何使用头文件 .h 编译 C 源码

    在 C 语言中,头文件或包含文件通常是一个源代码文件,程序员使用编译器指令将头文件包含进其他源文件的开始(或头部),由编译器在处理另一个源文件时自动包含进来. 一个头文件一般包含类.子程序.变量和其他 ...

  8. Python时间戳与时间字符串互相转换实例代码

    #设a为字符串import timea = "2011-09-28 10:00:00" #中间过程,一般都需要将字符串转化为时间数组time.strptime(a,'%Y-%m-% ...

  9. MQTT服务器搭建--Mosquitto用户名密码配置

    Mosquitto用户认证配置 前言:基于Mosquitto服务器已经搭建成功,大部分都是采用默认的是允许匿名用户登录模式,正式上线的系统需要进行用户认证. 1.用户参数说明 Mosquitto服务器 ...

  10. 通过设置P3P头来实现跨域访问COOKIE

    通过设置P3P头来实现跨域访问COOKIE 实际工作中,类似这样的要求很多,比如说,我们有两个域名,我们想实现在一个域名登录后,能自动完成另一个域名的登录,也就是PASSPORT的功能. 我只写一个大 ...