zoukankan      html  css  js  c++  java
  • [dp][单调队列] Jzoj P2569 股票交易

    题目描述

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

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

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

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

    输入输出格式

    输入格式:

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

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

    输出格式:

    输出数据为一行,包括 11 个数字,表示  ext{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% 的数据,0leq W<Tleq 50,1leq ext{MaxP}leq500W<T50,1MaxP50

    对于 50\%50% 的数据,0leq W<Tleq 2000,1leq ext{MaxP}leq500W<T2000,1MaxP50

    对于 100\%100% 的数据,0leq W<Tleq 2000,1leq ext{MaxP}leq20000W<T2000,1MaxP2000

    对于所有的数据,1leq BP_ileq AP_ileq 1000,1leq AS_i,BS_ileq ext{MaxP}1BPiAPi1000,1ASi,BSiMaxP

    题解

    • 其实这题可以用dp来做,设f[i][j]为第i天拥有数量为j的股票能赚的最大金额
    • 那么转移其实很显然,有四种情况
    • ①凭空买,f[i][j]=-j*ap
    • ②不买不卖,f[i][j]=max(f[i][j-1],f[i][j])
    • ③在之前的基础上买,f[i][j]=max(f[i][j],f[i-w-1][k]-(j-k)*ap)
    • 为什么只有i-w-1呢,因为i-w-2其实在第二种情况时候已经转移到i-w-1了,所以可以只做i-w-1
    • ④在之前的基础上卖,f[i][j]=max(f[i][j],f[i-w-1][k]+(k-j)*bp)
    • 那么怎么用单调队列优化呢,考虑一下直接dp是三次方的,要做到二次方
    • 三四的情况的式子,f[i][j]=max(f[i][j],f[i-w-1][k]-j*ap+k*ap),f[i][j]=max(f[i][j],f[i-w-1][k]-j*ap)+k*ap
    • 第四种情况也是类似的,那么这样的话可以发现,其实就是在找一个滑动窗口的最大值
    • 显然可以单调队列

    代码

     1 #include <cstdio>
     2 #include <iostream>
     3 #include <cstring>
     4 using namespace std;
     5 int n,m,w,ans,f[2010][2010],Q[2010];
     6 int main()
     7 {
     8     scanf("%d%d%d",&n,&m,&w);
     9     memset(f,128,sizeof(f));
    10     for (int i=1,ap,bp,as,bs;i<=n;i++)    
    11     {
    12         scanf("%d%d%d%d",&ap,&bp,&as,&bs);
    13         for (int j=0;j<=as;j++) f[i][j]=-ap*j;
    14         for (int j=0;j<=m;j++) f[i][j]=max(f[i][j],f[i-1][j]);
    15         if (i<=w) continue;
    16         int head=1,tail=0;
    17         for (int j=0;j<=m;j++)
    18         {
    19             while (head<=tail&&Q[head]<j-as) head++;
    20             while (head<=tail&&f[i-w-1][Q[tail]]+Q[tail]*ap<=f[i-w-1][j]+j*ap) tail--;
    21             Q[++tail]=j;
    22             if (head<=tail) f[i][j]=max(f[i][j],f[i-w-1][Q[head]]+Q[head]*ap-j*ap);
    23         }
    24         head=1; tail=0;
    25         for (int j=m;j>=0;j--)
    26         {
    27             while (head<=tail&&Q[head]>j+bs) head++;
    28             while (head<=tail&&f[i-w-1][Q[tail]]+Q[tail]*bp<=f[i-w-1][j]+j*bp) tail--;
    29             Q[++tail]=j;
    30             if (head<=tail) f[i][j]=max(f[i][j],f[i-w-1][Q[head]]+Q[head]*bp-j*bp);
    31         }
    32     }
    33     for (int i=0;i<=m;i++) ans=max(ans,f[n][i]);
    34     printf("%d",ans);
    35 }
  • 相关阅读:
    设计模式六大原则(PHP)
    composer update 或者 composer install提示killed解决办法
    运行composer出现do not run Composer as root/super user!
    composer install报错intervention/image 2.4.x-dev requires ext-fileinfo * -> the requested PHP extension fileinfo is missing from your system.
    laravel执行数据库迁移的过程中出现IlluminateDatabaseQueryException : SQLSTATE[HY000] [2002] Operation timed out (SQL: select * from information_schema.tables where table_schema = shop and table_name = migrations
    docker删除mysql镜像失败Error response from daemon: conflict: unable to delete 8809d5286227 (must be forced)
    测试开发岗,面试必看
    Python遍历字典去key和value需要注意的点→enumerate和items()
    Python→整数反转
    我去阿里、头条、京东的面试经(测开)
  • 原文地址:https://www.cnblogs.com/Comfortable/p/9859994.html
Copyright © 2011-2022 走看看