• BZOJ1855: [Scoi2010]股票交易


    Description

    最近lxhgww又迷上了投资股票,通过一段时间的观察和学习,他总结出了股票行情的一些规律。 通过一段时间的观察,lxhgww预测到了未来T天内某只股票的走势,第i天的股票买入价为每股APi,第i天的股票卖出价为每股BPi(数据保证对于每个i,都有APi>=BPi),但是每天不能无限制地交易,于是股票交易所规定第i天的一次买入至多只能购买ASi股,一次卖出至多只能卖出BSi股。 另外,股票交易所还制定了两个规定。为了避免大家疯狂交易,股票交易所规定在两次交易(某一天的买入或者卖出均算是一次交易)之间,至少要间隔W天,也就是说如果在第i天发生了交易,那么从第i+1天到第i+W天,均不能发生交易。同时,为了避免垄断,股票交易所还规定在任何时间,一个人的手里的股票数不能超过MaxP。 在第1天之前,lxhgww手里有一大笔钱(可以认为钱的数目无限),但是没有任何股票,当然,T天以后,lxhgww想要赚到最多的钱,聪明的程序员们,你们能帮助他吗?

    Input

    输入数据第一行包括3个整数,分别是T,MaxP,W。 接下来T行,第i行代表第i-1天的股票走势,每行4个整数,分别表示APi,BPi,ASi,BSi。

    Output

    输出数据为一行,包括1个数字,表示lxhgww能赚到的最多的钱数。

    Sample Input

    5 2 0
    2 1 1 1
    2 1 1 1
    3 2 1 1
    4 3 1 1
    5 4 1 1

    Sample Output

    3

    HINT

    对于30%的数据,0<=W<T<=50,1<=MaxP<=50
    对于50%的数据,0<=W<T<=2000,1<=MaxP<=50
    对于100%的数据,0<=W<T<=2000,1<=MaxP<=2000
    对于所有的数据,1<=BPi<=APi<=1000,1<=ASi,BSi<=MaxP

    怎么感觉做单调队列优化着优化着没找到感觉结果巨***儿模糊??

    一眼方程f[i][j]表示第i天手里有j张股票,三种转移:

    考虑优化,上下界单调,单调队列

    然后推柿子,把固定项i提出来,然后剩下的分两种情况讨论即可(雾??复杂度O(nm)

    代码如下:

     1 //MT_LI
     2 #include<cmath>
     3 #include<cstdio>
     4 #include<cstring>
     5 #include<cstdlib>
     6 #include<algorithm>
     7 using namespace std;
     8 int f[2100][2100];//表示第i天手里有j套股票的最优策略
     9 /*
    10 不买不卖    f[i][j]=f[i-1][j]
    11     买入    f[i][j]=f[i-w-1][k]-ap[i]*(j-k)|k>=j-as
    12             f[i][j]=f[i-w-1][k]-ap[i]*j+ap[i]*k
    13             
    14     卖出     f[i][j]=f[i-w-1][k]+bp[i]*(k-j)|k<=j+bs
    15 */ 
    16 struct node{
    17     int ap,bp,as,bs;
    18 }a[4100];int n,m,w;
    19 int head,tail;
    20 struct line{
    21     int pos,x;
    22 }list[4100];
    23 int main()
    24 {
    25     scanf("%d%d%d",&n,&m,&w);
    26     for(int i=1;i<=n;i++)scanf("%d%d%d%d",&a[i].ap,&a[i].bp,&a[i].as,&a[i].bs);
    27     for(int i=1;i<=m;i++)f[0][i]=-99999999;
    28     for(int i=1;i<=n;i++)
    29     {
    30         head=1,tail=0;
    31         for(int j=0;j<=m;j++)
    32         {
    33             f[i][j]=f[i-1][j];
    34             if(i<=w){if(j<=a[i].as)f[i][j]=max(f[i][j],-j*a[i].ap);continue;}
    35             while(head<=tail&&list[head].pos<j-a[i].as)head++;
    36             if(head<=tail)f[i][j]=max(f[i][j],list[head].x-a[i].ap*j);
    37             while(head<=tail&&list[tail].x<f[i-w-1][j]+a[i].ap*j)tail--;
    38             list[++tail].x=f[i-w-1][j]+a[i].ap*j;
    39             list[tail].pos=j;
    40         }
    41         head=1,tail=0;
    42         if(i>w)
    43         {
    44             for(int j=m;j>=0;j--)
    45             {
    46                 while(head<=tail&&list[head].pos>j+a[i].bs)head++;
    47                 if(head<=tail)f[i][j]=max(f[i][j],list[head].x-a[i].bp*j);
    48                 while(head<=tail&&list[tail].x<f[i-w-1][j]+a[i].bp*j)tail--;
    49                 list[++tail].x=f[i-w-1][j]+a[i].bp*j;
    50                 list[tail].pos=j;
    51             }
    52         }
    53     }
    54     printf("%d
    ",f[n][0]);
    55     return 0;
    56 }
    The deepest love I think,later than apart,I will live as you like
  • 相关阅读:
    什么是线程组,为什么在 Java 中不推荐使用?
    什么是 FutureTask?使用 ExecutorService 启动任务?
    Java 中用到的线程调度算法是什么?
    什么是阻塞队列?阻塞队列的实现原理是什么?如何使用 阻塞队列来实现生产者-消费者模型?
    说说对 SQL 语句优化有哪些方法?(选择几条)
    什么是 Executors 框架?
    Java Concurrency API 中的 Lock 接口(Lock interface) 是什么?对比同步它有什么优势?
    什么是原子操作?在 Java Concurrency API 中有哪些原 子类(atomic classes)?
    Java 中你怎样唤醒一个阻塞的线程?
    你将如何使用 thread dump?你将如何分析 Thread dump?
  • 原文地址:https://www.cnblogs.com/MT-LI/p/9649151.html
Copyright © 2020-2023  润新知