【单调队列优化dp】HDU 3401 Trade
http://acm.hdu.edu.cn/showproblem.php?pid=3401
【题意】
- 知道之后n天的股票买卖价格(api,bpi),以及每天股票买卖数量上限(asi,bsi),问他最多能赚多少钱。开始时有无限本金,要求任两次交易需要间隔W天以上,即第i天交易,第i+w+1天才能再交易。同时他任意时刻最多只能拥有maxp的股票
【思路】
- dp[i][j]表示第i天拥有j支股票的最大收益,有三种转移方案:
- dp[i][j]=max(dp[i][j],dp[i-1][j])表示第i天不买也不卖,由前一天转移而来
- dp[i][j]=max(dp[i][j],dp[i-w-1][k]-(j-k)*ap[i])表示第i天买股票,有第i-w-1天转移而来
- dp[i][j]=max(dp[i][j],dp[i-w-1][k]+(k-j)*bp[i])表示第i天卖股票,有第i-w-1天转移而来
- 注意只需计算由i-w-1天转移而来,因为i-w-1天前的最优值已经通过不买不卖转移到了i-w-1天,即dp[i][j],j固定是随i单调递增的
- 现在dp的复杂度是n^3,怎样降低复杂度?
- 分析买股票的情况,dp[i][j]=max(dp[i-w-1][k]+k*ap[i])-j*ap[j],类似a[i]=max(b[k])+c[i],可以用单调队列优化
- 我理解的是,状态数为2D,转移为1D,然后又有单调性,可以固定一维状态,把转移均摊到另一维,相当于转移是O(1)的,所以单调队列可以把dp降一维
- a[i]=max(b[k]),若k<=j是从前往后递推,若k>=j是从后往前递推
【AC】
- #include<bits/stdc++.h>
- using namespace std;
- typedef long long ll;
- const int maxn=2e3+;
- const int inf=0x3f3f3f3f;
- int ap[maxn],bp[maxn],as[maxn],bs[maxn];
- int n,maxp,w;
- int dp[maxn][maxn];
- struct node
- {
- int x;
- int num;
- }q[maxn];
- int main()
- {
- int T;
- scanf("%d",&T);
- while(T--)
- {
- memset(dp,-inf,sizeof(dp));//求最大值,所以初始化为无穷小
- scanf("%d%d%d",&n,&maxp,&w);
- for(int i=;i<=n;i++) scanf("%d%d%d%d",&ap[i],&bp[i],&as[i],&bs[i]);
- for(int i=;i<=n;i++) dp[i][]=;//拥有股票为0的最大收益当前是0
- //前w+1天和[w+2,n]要分开算
- //前w+1天只有两种情况:1.每天都不买不卖 2.其中一天买了股票 不能卖股票,而且最多只有一天能交易
- for(int i=;i<=w+;i++)
- {
- for(int j=;j<=as[i];j++)
- {
- dp[i][j]=-j*ap[i];//可以选择在当天买
- }
- }
- for(int j=;j<=maxp;j++)
- {
- for(int i=;i<=w+;i++)
- {
- dp[i][j]=max(dp[i][j],dp[i-][j]);//也可以选择由前一天转移而来
- }
- }
- for(int i=w+;i<=n;i++)
- {
- int head=,tail=;
- for(int j=;j<=maxp;j++)
- {
- dp[i][j]=max(dp[i][j],dp[i-][j]);//不买也不卖
- //dp[i][j]=max(dp[i-w-1][k]+k*ap[i])-j*ap[i],其中k<=j
- while(head<=tail&&q[tail].x<=dp[i-w-][j]+j*ap[i]) tail--;
- q[++tail].x=dp[i-w-][j]+j*ap[i];q[tail].num=j;
- while(q[head].num+as[i]<j) head++;
- dp[i][j]=max(dp[i][j],q[head].x-j*ap[i]);
- }
- //dp[i][j]=max(dp[i-w-1][k]+k*bp[i])-j*bp[i],其中k>=j
- head=,tail=;
- for(int j=maxp;j>=;j--)
- {
- while(head<=tail&&q[tail].x<=dp[i-w-][j]+j*bp[i]) tail--;
- q[++tail].x=dp[i-w-][j]+j*bp[i];q[tail].num=j;
- while(q[head].num>bs[i]+j) head++;
- dp[i][j]=max(dp[i][j],q[head].x-j*bp[i]);
- }
- }
- int ans=;
- for(int i=;i<=maxp;i++)
- {
- ans=max(ans,dp[n][i]);
- }
- printf("%d\n",ans);
- }
- return ;
- }
单调队列优化dp
【单调队列优化dp】HDU 3401 Trade的更多相关文章
- 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 ...
- 单调队列优化DP,多重背包
单调队列优化DP:http://www.cnblogs.com/ka200812/archive/2012/07/11/2585950.html 单调队列优化多重背包:http://blog.csdn ...
- 单调队列优化DP——习题收集
前言 感觉可以用单调队列优化dp的模型还是挺活的,开个随笔记录一些遇到的比较有代表性的模型,断续更新.主要做一个收集整理总结工作. 记录 0x01 POJ - 1821 Fence,比较适合入门的题, ...
- Parade(单调队列优化dp)
题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=2490 Parade Time Limit: 4000/2000 MS (Java/Others) ...
- 1855: [Scoi2010]股票交易[单调队列优化DP]
1855: [Scoi2010]股票交易 Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 1083 Solved: 519[Submit][Status] ...
- 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 ...
- hdu3401:单调队列优化dp
第一个单调队列优化dp 写了半天,最后初始化搞错了还一直wa.. 题目大意: 炒股,总共 t 天,每天可以买入na[i]股,卖出nb[i]股,价钱分别为pa[i]和pb[i],最大同时拥有p股 且一次 ...
- BZOJ_3831_[Poi2014]Little Bird_单调队列优化DP
BZOJ_3831_[Poi2014]Little Bird_单调队列优化DP Description 有一排n棵树,第i棵树的高度是Di. MHY要从第一棵树到第n棵树去找他的妹子玩. 如果MHY在 ...
- 【单调队列优化dp】 分组
[单调队列优化dp] 分组 >>>>题目 [题目] 给定一行n个非负整数,现在你可以选择其中若干个数,但不能有连续k个数被选择.你的任务是使得选出的数字的和最大 [输入格式] ...
随机推荐
- 解决更新到os x10.11后openssl头文件无法找到的问题
os x从10.10更新到10.11后,原有代码编译报错,#include <openssl/ssl.h>等头文件无法找到: "openssl/ssl.h: No such fi ...
- jmeter动态参数传值配置
jmeter动态参数传值配置
- 爬虫基本原理及requests,response详解
一.爬虫基本原理 1.爬虫是什么 #1.什么是互联网? 互联网是由网络设备(网线,路由器,交换机,防火墙等等)和一台台计算机连接而成,像一张网一样. #2.互联网建立的目的? 互联网的核心价值在于数据 ...
- Spring 配置定时器(注解+xml)方式—整理
一.注解方式 1. 在Spring的配置文件ApplicationContext.xml,首先添加命名空间 xmlns:task="http://www.springframework.or ...
- Slacklining 2017/2/6
原文 Get ready for a different kind of challenge What happens when mountain climbers take a day off?Ap ...
- (三)SpringMVC之常用注解
SpringMVC的常用注解 注解 说明 @Controller 用于说明这个类是一个控制器 @RequestMapping 用于注释一个控制器类或者控制器类的方法 @RequestParam 用于将 ...
- windows8无脑式双系统安装教程(转)
转:http://blog.csdn.net/poem_qianmo/article/details/7334987 首先去微软官网将ISO文件下载下来,分为32bit跟64bit两个版本,因人而异, ...
- 开源项目: circular-progress-button
带进度条显示的按钮, 其效果如下所示: 其由三部分动画组成: 初始状态->圆环状态->完成状态. 0. 实现从初始到圆环的简单实现: 继承自button 类, 设置其背景 public c ...
- 利用python实现整数转换为任意进制字符串
假设你想将一个整数转换为一个二进制和十六进制字符串.例如,将整数 10 转换为十进制字符串表示为 10 ,或将其字符串表示为二进制 1010 . 实现 以 2 到 16 之间的任何基数为参数: def ...
- CSS BEM 命名规范简介
[前言] BEM 是一个简单又非常有用的命名约定.让你的前端代码更容易阅读和理解,更容易协作,更容易控制,更加健壮和明确,而且更加严密.这篇文章主要介绍了CSS BEM 命名规范简介(推荐)的相关资料 ...