[SCOI2010]股票交易

[SCOI2010]股票交易

推荐的相关题目显示

题目描述

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

通过一段时间的观察,lxhgww 预测到了未来 T 天内某只股票的走势,第 i 天的股票买入价为每股 APi?,第 i 天的股票卖出价为每股 BPi?(数据保证对于每个 i,都有 APi?≥BPi?),但是每天不能无限制地交易,于是股票交易所规定第 i 天的一次买入至多只能购买 ASi? 股,一次卖出至多只能卖出 BSi? 股。

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

一个人的手里的股票数不能超过MaxP。

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

输入输出格式

输入格式:

输入数据第一行包括 3 个整数,分别是 T,MaxP,W。

接下来 T 行,第 i 行代表第 i?1 天的股票走势,每行 4 个整数,分别表示 APi?, BPi?, ASi?, BSi?。

输出格式:

输出数据为一行,包括 1 个数字,表示 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

/*
思路:
对于我这样的蒟蒻来说是一道难题
首先我们努力的列出一个DP式子
dp[i][j]表示第i天持有j支股票
那么我们便有四个决策
首先如果持有股量不超当日上界的情况直接购入(其实这种决策被第三种决策完全包括,反正你加上了也不影响正确性)
第二,我们不买也不卖,dp[i][j]=dp[i-1][j];
第三,我们买入x支股(x<=as[i]) dp[i][j]=max(dp[i][j],dp[i-m-1][j-y])(1<=y<=min(j,as[i]))
第四,我们出手x支股,与上种决策类似
这样的时间复杂度是O(TMaxPW) 期望50pts
然后,可以发现dp[i-m-1][j-y]的j-y为单调上升,这样我们可以用单调队列维护一下
然后,时间复杂度变成O(TMAXP)
应该就可以通过除了COJ以外一切测评机了
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<time.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
deque<pair<int,int> > Q,P;
int ap[2005],bp[2050],as[2020],bs[2050],dp[2050][2050],n,m,t;
int main(){
	scanf("%d%d%d",&n,&t,&m);
	m++;
	rep(i,1,n) scanf("%d%d%d%d",&ap[i],&bp[i],&as[i],&bs[i]);
	rep(i,1,t) dp[0][i]=-99999999;
	rep(i,1,n){
		if(i<=m){
			rep(j,0,t){
				dp[i][j]=dp[i-1][j];
				if(j<=as[i] && dp[i][j]<-j*ap[i]) dp[i][j]=-j*ap[i];
				//printf("dp[%d][%d]=%d\n",i,j,dp[i][j]);
			}
			continue;
		}
		while(!Q.empty()) Q.pop_back();
		while(!P.empty()) P.pop_back();
		rep(j,1,min(t,bs[i])){
			while(!Q.empty() && Q.back().second<=dp[i-m][j]+j*bp[i]) Q.pop_back();
            Q.push_back(make_pair(j,dp[i-m][j]+j*bp[i]));
		}
		rep(j,0,t){
			dp[i][j]=dp[i-1][j];
			if(j<=as[i] && dp[i][j]<=-j*ap[i]) dp[i][j]=-j*ap[i];
			if(!Q.empty() && !P.empty()) dp[i][j]=max(dp[i][j],max(Q.front().second-j*bp[i],P.front().second-j*ap[i]));
			else if(!Q.empty()) dp[i][j]=max(dp[i][j],Q.front().second-j*bp[i]);
			else if(!P.empty()) dp[i][j]=max(dp[i][j],P.front().second-j*ap[i]);
			while(!Q.empty() && Q.front().first==j+1) Q.pop_front();
			while(!P.empty() && P.front().first+as[i]<j+1) P.pop_front();
			while(!Q.empty() && j+bs[i]+1<=t && Q.back().second<=dp[i-m][j+bs[i]+1]+bp[i]*(j+bs[i]+1)) Q.pop_back();
			while(!P.empty() && P.back().second<=dp[i-m][j]+ap[i]*j) P.pop_back();
			P.push_back(make_pair(j,dp[i-m][j]+ap[i]*j));
			if(j+bs[i]+1<=t) Q.push_back(make_pair(j+bs[i]+1,dp[i-m][j+bs[i]+1]+bp[i]*(j+bs[i]+1)));
		}
	}
	printf("%d",dp[n][0]);
	return 0;
}

  

原文地址:https://www.cnblogs.com/handsome-zlk/p/10049189.html

时间: 2024-08-29 03:57:31

[SCOI2010]股票交易的相关文章

1855: [Scoi2010]股票交易[单调队列优化DP]

1855: [Scoi2010]股票交易 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 1083  Solved: 519[Submit][Status][Discuss] Description 最近lxhgww又迷上了投资股票,通过一段时间的观察和学习,他总结出了股票行情的一些规律. 通过一段时间的观察,lxhgww预测到了未来T天内某只股票的走势,第i天的股票买入价为每股APi,第i天的股票卖出价为每股BPi(数据保证对于每个i,都有APi>=

洛谷P2569 [SCOI2010]股票交易

P2569 [SCOI2010]股票交易 题目描述 最近lxhgww又迷上了投资股票,通过一段时间的观察和学习,他总结出了股票行情的一些规律. 通过一段时间的观察,lxhgww预测到了未来T天内某只股票的走势,第i天的股票买入价为每股APi,第i天的股票卖出价为每股BPi(数据保证对于每个i,都有APi>=BPi),但是每天不能无限制地交易,于是股票交易所规定第i天的一次买入至多只能购买ASi股,一次卖出至多只能卖出BSi股. 另外,股票交易所还制定了两个规定.为了避免大家疯狂交易,股票交易所规

bzoj 1855: [Scoi2010]股票交易

Description 最近lxhgww又迷上了投资股票,通过一段时间的观察和学习,他总结出了股票行情的一些规律. 通过一段时间的观察,lxhgww预测到了未来T天内某只股票的走势,第i天的股票买入价为每股APi,第i天的股票卖出价为每股BPi(数据保证对于每个i,都有APi>=BPi),但是每天不能无限制地交易,于是股票交易所规定第i天的一次买入至多只能购买ASi股,一次卖出至多只能卖出BSi股. 另外,股票交易所还制定了两个规定.为了避免大家疯狂交易,股票交易所规定在两次交易(某一天的买入或

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-1][k]+k*Ap[i]的单调性即可 1 #include<stdio.h> 2 #include<string.h> 3 #include<algorithm> 4 using namespace std; 5 const int maxn = 2010; 6 int

BZOJ 1855 [Scoi2010]股票交易 单调队列优化DP

题意:链接 方法:单调队列优化DP 解析:噢又是一道情况很多的题,然而三种更新我又落下一种导致样例不过,后来看题解才恍然- -最SB的一种更新居然忘了. 状态好想f[i][j]代表前i天有j双袜子时的最大利润. 三种更新: 第一种:f[i][j]=max(f[i][j],f[i?1][j]):(然而我忘了这一种) 第二种:买入f[i][j]=max(f[i][j],f[i?w?1][k]?(j?k)?a[i].ap)(k>=j?a[i].as); 第三种:卖出f[i][j]=max(f[i][j

●BZOJ 1855 [Scoi2010]股票交易

题链: http://www.lydsy.com/JudgeOnline/problem.php?id=1855 题解: DP,单调队列优化.(好久没做 DP题,居然还意外地想出来了) 定义 dp[i][k] 表示前 i天,手上还有 k股的最大收益.(注意这个定义是个前缀的形式)假设枚举到了第 i天,令 j=i-W-1.那么dp[i][]就由dp[j][]转移而来.(说了是前缀形式的啦,就不要去枚举 j-1,j-2...了)转移还是比较显然的:枚举第 i 天结束手上还剩的股数 k:      

Bzoj1855: [Scoi2010]股票交易

题面 Bzoj Sol 设\(f[i][j]\)表示第\(i\)天有\(j\)张股票的最大收益 转移很简单辣 # include <bits/stdc++.h> # define RG register # define IL inline # define Fill(a, b) memset(a, b, sizeof(a)) using namespace std; typedef long long ll; const int _(2010); IL int Input(){ RG int

洛谷 [SCOI2010]股票交易 | 单调性DP

题目链接 #include<cstdio> #include<algorithm> #include<cstring> #define N 2005 using namespace std; int n,q[N],ap,bp,dp[N][N],as,bs,m,w; int main() { scanf("%d%d%d",&n,&m,&w); memset(dp,128,sizeof(dp)); for (int i=1;i&l

【bzoj1855】 [Scoi2010]股票交易

上一篇blog已经讲了单调队列与单调栈的用法,本篇将讲述如何借助单调队列优化dp. 我先丢一道题:bzoj1855 此题不难想出O(n^4)做法,我们用f[i][j]表示第i天手中持有j只股票时,所赚钱的最大值. 不难推出以下式子: $f[i][j]=max\left\{\begin{aligned}f[k][l]+(l-j)\times bs[i] , l \in [j,j+bs[i]]\\f[k][l]-(j-l)\times as[i] , l \in [j-as[i],j]\\\end{