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】

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. typedef long long ll;
  4. const int maxn=2e3+;
  5. const int inf=0x3f3f3f3f;
  6. int ap[maxn],bp[maxn],as[maxn],bs[maxn];
  7. int n,maxp,w;
  8. int dp[maxn][maxn];
  9. struct node
  10. {
  11. int x;
  12. int num;
  13. }q[maxn];
  14. int main()
  15. {
  16. int T;
  17. scanf("%d",&T);
  18. while(T--)
  19. {
  20. memset(dp,-inf,sizeof(dp));//求最大值,所以初始化为无穷小
  21. scanf("%d%d%d",&n,&maxp,&w);
  22. for(int i=;i<=n;i++) scanf("%d%d%d%d",&ap[i],&bp[i],&as[i],&bs[i]);
  23. for(int i=;i<=n;i++) dp[i][]=;//拥有股票为0的最大收益当前是0
  24. //前w+1天和[w+2,n]要分开算
  25. //前w+1天只有两种情况:1.每天都不买不卖 2.其中一天买了股票 不能卖股票,而且最多只有一天能交易
  26. for(int i=;i<=w+;i++)
  27. {
  28. for(int j=;j<=as[i];j++)
  29. {
  30. dp[i][j]=-j*ap[i];//可以选择在当天买
  31. }
  32. }
  33. for(int j=;j<=maxp;j++)
  34. {
  35. for(int i=;i<=w+;i++)
  36. {
  37. dp[i][j]=max(dp[i][j],dp[i-][j]);//也可以选择由前一天转移而来
  38. }
  39. }
  40. for(int i=w+;i<=n;i++)
  41. {
  42. int head=,tail=;
  43. for(int j=;j<=maxp;j++)
  44. {
  45. dp[i][j]=max(dp[i][j],dp[i-][j]);//不买也不卖
  46. //dp[i][j]=max(dp[i-w-1][k]+k*ap[i])-j*ap[i],其中k<=j
  47. while(head<=tail&&q[tail].x<=dp[i-w-][j]+j*ap[i]) tail--;
  48. q[++tail].x=dp[i-w-][j]+j*ap[i];q[tail].num=j;
  49. while(q[head].num+as[i]<j) head++;
  50. dp[i][j]=max(dp[i][j],q[head].x-j*ap[i]);
  51. }
  52. //dp[i][j]=max(dp[i-w-1][k]+k*bp[i])-j*bp[i],其中k>=j
  53. head=,tail=;
  54. for(int j=maxp;j>=;j--)
  55. {
  56. while(head<=tail&&q[tail].x<=dp[i-w-][j]+j*bp[i]) tail--;
  57. q[++tail].x=dp[i-w-][j]+j*bp[i];q[tail].num=j;
  58. while(q[head].num>bs[i]+j) head++;
  59. dp[i][j]=max(dp[i][j],q[head].x-j*bp[i]);
  60. }
  61. }
  62. int ans=;
  63. for(int i=;i<=maxp;i++)
  64. {
  65. ans=max(ans,dp[n][i]);
  66. }
  67. printf("%d\n",ans);
  68. }
  69.  
  70. return ;
  71. }

单调队列优化dp

【单调队列优化dp】HDU 3401 Trade的更多相关文章

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

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

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

  3. 单调队列优化DP——习题收集

    前言 感觉可以用单调队列优化dp的模型还是挺活的,开个随笔记录一些遇到的比较有代表性的模型,断续更新.主要做一个收集整理总结工作. 记录 0x01 POJ - 1821 Fence,比较适合入门的题, ...

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

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

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

    1855: [Scoi2010]股票交易 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 1083  Solved: 519[Submit][Status] ...

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

  7. hdu3401:单调队列优化dp

    第一个单调队列优化dp 写了半天,最后初始化搞错了还一直wa.. 题目大意: 炒股,总共 t 天,每天可以买入na[i]股,卖出nb[i]股,价钱分别为pa[i]和pb[i],最大同时拥有p股 且一次 ...

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

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

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

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

随机推荐

  1. 解决更新到os x10.11后openssl头文件无法找到的问题

    os x从10.10更新到10.11后,原有代码编译报错,#include <openssl/ssl.h>等头文件无法找到: "openssl/ssl.h: No such fi ...

  2. jmeter动态参数传值配置

    jmeter动态参数传值配置

  3. 爬虫基本原理及requests,response详解

    一.爬虫基本原理 1.爬虫是什么 #1.什么是互联网? 互联网是由网络设备(网线,路由器,交换机,防火墙等等)和一台台计算机连接而成,像一张网一样. #2.互联网建立的目的? 互联网的核心价值在于数据 ...

  4. Spring 配置定时器(注解+xml)方式—整理

    一.注解方式 1. 在Spring的配置文件ApplicationContext.xml,首先添加命名空间 xmlns:task="http://www.springframework.or ...

  5. Slacklining 2017/2/6

    原文 Get ready for a different kind of challenge What happens when mountain climbers take a day off?Ap ...

  6. (三)SpringMVC之常用注解

    SpringMVC的常用注解 注解 说明 @Controller 用于说明这个类是一个控制器 @RequestMapping 用于注释一个控制器类或者控制器类的方法 @RequestParam 用于将 ...

  7. windows8无脑式双系统安装教程(转)

    转:http://blog.csdn.net/poem_qianmo/article/details/7334987 首先去微软官网将ISO文件下载下来,分为32bit跟64bit两个版本,因人而异, ...

  8. 开源项目: circular-progress-button

    带进度条显示的按钮, 其效果如下所示: 其由三部分动画组成: 初始状态->圆环状态->完成状态. 0. 实现从初始到圆环的简单实现: 继承自button 类, 设置其背景 public c ...

  9. 利用python实现整数转换为任意进制字符串

    假设你想将一个整数转换为一个二进制和十六进制字符串.例如,将整数 10 转换为十进制字符串表示为 10 ,或将其字符串表示为二进制 1010 . 实现 以 2 到 16 之间的任何基数为参数: def ...

  10. CSS BEM 命名规范简介

    [前言] BEM 是一个简单又非常有用的命名约定.让你的前端代码更容易阅读和理解,更容易协作,更容易控制,更加健壮和明确,而且更加严密.这篇文章主要介绍了CSS BEM 命名规范简介(推荐)的相关资料 ...