洛谷P2569 股票交易【dp】【单调队列】
题目描述
最近 \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 能赚到的最多的钱数。
输入输出样例
说明
对于 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】【单调队列】的更多相关文章
- 洛谷P2569 股票交易 [SCOI2010] dp
正解:dp+单调队列优化 解题报告: 先放个传送门鸭qwq umm首先dp转移挺好想的?就买和不买 f[i][j]表示第i天手上有j的股份的最多钱,转移也很好想?就枚举第1天到第i-w-1天枚举买k股 ...
- 【Luogu】P2569股票交易(单调队列优化DP)
题目链接 首先这题可以肯定的是朴素DP秒出.然后单调队列优化因为没接触过所以不会emmm 而且脑补没补出来 坐等四月省选倒数第一emmm 心态爆炸,偷懒放题解链接 #include<cstdio ...
- P2569 [SCOI2010]股票交易 dp 单调队列优化
LINK:股票交易 题目确实不算难 但是坑点挺多 关于初值的处理问题我就wa了两次. 所以来谢罪. 由于在手中的邮票的数量存在限制 且每次买入卖出也有限制. 必然要多开一维来存每天的邮票数量. 那么容 ...
- 洛谷P2569 股票交易
题目传送门https://www.luogu.org/problemnew/show/P2569 第一眼看题就觉得是个dp ,然后看到2000的范围,hmm大概是个n^2的2维dp 开始设状态,第一维 ...
- 洛谷P1776--宝物筛选(单调队列+多重背包)
https://www.luogu.org/problemnew/show/P1776 单调队列+多重背包的讲解https://www.cnblogs.com/JoeFan/p/4165956.htm ...
- 【洛谷】【动态规划+单调队列】P1714 切蛋糕
[题目描述:] 今天是小Z的生日,同学们为他带来了一块蛋糕.这块蛋糕是一个长方体,被用不同色彩分成了N个相同的小块,每小块都有对应的幸运值. 小Z作为寿星,自然希望吃到的第一块蛋糕的幸运值总和最大,但 ...
- 【洛谷】【动态规划+单调队列】P1725 琪露诺
[题目描述:] 在幻想乡,琪露诺是以笨蛋闻名的冰之妖精. 某一天,琪露诺又在玩速冻青蛙,就是用冰把青蛙瞬间冻起来.但是这只青蛙比以往的要聪明许多,在琪露诺来之前就已经跑到了河的对岸.于是琪露诺决定到河 ...
- 【BZOJ1855】[Scoi2010]股票交易 DP+单调队列
[BZOJ1855][Scoi2010]股票交易 Description 最近lxhgww又迷上了投资股票,通过一段时间的观察和学习,他总结出了股票行情的一些规律. 通过一段时间的观察,lxhgww预 ...
- 洛谷luogu3957跳房子(单调队列优化)
QwQ被普及组的题折磨的死去活来. 硬是卡线段树,没卡过QwQ oi生涯,第一道正经的单调队列dp题 进入正题 题目大意: 其中\(n \le 500000\) 看到这个题的第一感觉就是二分金币数 很 ...
随机推荐
- Linux┊理解devfs、sysfs、udev、tmpfs等各种文件系统
https://www.cnblogs.com/yangliheng/p/6187193.html https://blog.csdn.net/qq258711519/article/details/ ...
- convertView&setTag方法的一点理解
前言 首先我们要知道setTag方法是干什么的,SDK解释为 Tags Unlike IDs, tags are not used to identify views. Tags are essent ...
- oracle sqlplus常用命令大全
show和set命令是两条用于维护SQL*Plus系统变量的命令 SQL> show all --查看所有68个系统变量值 SQL> show user --显示当前连接用户 SQL> ...
- SpringMVC由浅入深day02_10拦截器
10 拦截器 Spring Web MVC 的处理器拦截器类似于Servlet 开发中的过滤器Filter,用于对处理器进行预处理和后处理. 10.1 拦截定义 定义拦截器,实现HandlerInte ...
- Android图片的合成示例
package com.example.demo; import android.os.Bundle; import android.app.Activity; import android.grap ...
- 使用CountDownLatch模拟高并发场景
import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java ...
- iOS开发--打印NSRange,CGRect等结构体
使用对应的转换NSStringFromCGPoint NSStringFromCGSize NSStringFromCGRect NSStringFromCGAffineTransform ...
- nodeJs学习过程之一个图片上传显示的例子
目标 1. 在浏览器地址栏输入“http://demos/start”,进入欢迎页面,页面有一个文件上传表单: 2. 选择一张图片并提交表单,文件被上传到"http://demos/uplo ...
- Android学习之适配器ArrayAdapter SimpleAdapter
Adapter是个什么角色呢?其实它的作用就是View界面和数据之间的桥梁.我们可以看作是界面数据绑定的一种理解,它所操纵的数据一般都是一些比较复杂的数据,如数组,链表,数据库,集合等. 常用的适配器 ...
- SeaJS之use函数
有了 define 等模块定义规范的实现,我们可以开发出很多模块.但光有一堆模块不管用,我们还得让它们能跑起来.在 SeaJS 里,要启动模块系统很简单: <script src=”path/t ...