• BZOJ1855 股票交易 单调队列优化 DP


    描述

      某位蒟佬要买股票, 他神奇地能够预测接下来 T 天的 每天的股票购买价格 ap, 股票出售价格 bp, 以及某日购买股票的上限 as,  某日出售股票上限 bs, 并且每次股票交 ♂ 易 ( 购买与出售都属于交易 )都需要间隔 W 天,手头股票总数不能超过 maxp 个. 请你想办法赚到最多的钱.

      T , maxp <= 2000

      

    题解

      定义 F[ i ][ j ] 为到第 i 天, 剩余 j 张股票 , 能够赚到最多的钱。

      分如下几种情况:

    1.   股票仅从当天买: F[ i ][ j ] = - j * ap[ i ]
    2.        当天不买, 股票是之前买的 : F[ i ][ j ] = F[ i - 1][ j ]
    3.        在 w + 1 天之前的股票的基础上 购买若干股票得到: F[ i ][ j ] = F[ i - w - 1][ k ] - ( j - k ) * ap[ i ]    并且满足 j > k >= j - as
    4.        在 w + 1 天之前的股票的基础上 出售若干股票得到: F[ i ][ j ] = F[ i - w - 1][ k] + ( k - j ) * bp[ i ]    并且满足 j < k <= j + bs

      就可以写出一个 O(T * maxp * maxp) 的dp, 当然是 O (不能过)


      将 3 式子中的  F[ i - w - 1][ k ] + k * ap[i] 提取出来, 因为要满足最优解, 显然这个式子是越大越好, 又要满足 k >= j - as, 肯定是k 越大越好, 那么就可以用单调队列来进行优化

      4 式子也同理可得, 不过3, 4 需要分开处理

    代码

     

     1 #include<cstring>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #define rd read()
     5 #define rep(i,a,b) for( int i = (a); i <= (b); ++i )
     6 #define per(i,a,b) for( int i = (a); i >= (b); --i )
     7 using namespace std;
     8 
     9 const int N = 3e3;
    10 
    11 int t, ap[N], bp[N], as[N], bs[N], maxp, w, f[N][N], q[N];
    12 
    13 int read() {
    14     int X = 0, p = 1; char c = getchar();
    15     for(; c > '9' || c < '0'; c = getchar() ) if( c == '-' ) p = -1;
    16     for(; c >= '0' && c <= '9'; c = getchar()) X = X * 10 + c - '0';
    17     return X * p;
    18 }
    19 
    20 int cal1( int x ,int y ) {
    21     return f[x - w - 1][y] + ap[x] * y;
    22 }
    23 
    24 int cal2( int x, int y ) {
    25     return f[x - w - 1][y] + bp[x] * y;
    26 }
    27 
    28 int main()
    29 {
    30     t = rd, maxp = rd, w = rd;
    31     rep( i, 1, t ) ap[i] = rd, bp[i] = rd, as[i] =rd, bs[i] =rd;
    32     memset(f, 128, sizeof(f));
    33     f[0][0] = 0;
    34     rep( i, 1, t ) {
    35         rep( j, 0, as[i] ) f[i][j] = -ap[i] * j;
    36         rep( j, 0, maxp )f[i][j] = max( f[i][j], f[i - 1][j] );
    37         if( i <= w) continue;
    38         int l = 1, r = 0;
    39         rep( j, 0, maxp ) {
    40             while( l <= r && q[l] < j - as[i] ) l++;
    41             if( l <= r ) f[i][j] = max( f[i][j], f[i - w - 1][ q[l] ] - ap[i] * ( j - q[l] ) );
    42             while( l <= r && cal1( i, q[r] ) <= cal1( i, j ) ) r--;
    43             q[++r] = j;
    44         }
    45         l = 1, r = 0;
    46         per( j, maxp, 0 ) {
    47             while( l <= r && q[l] > j + bs[i] ) l++;
    48             if( l <= r ) f[i][j] = max( f[i][j], f[i - w - 1][q[l]] + bp[i] * ( q[l] - j ) );
    49             while( l <= r && cal2( i, q[r] ) <= cal2( i, j ) ) r--;
    50             q[++r] = j;
    51         }
    52     }
    53     int ans = 0;
    54     rep( i, 1, t ) ans = max( ans, f[i][0]);
    55     printf("%d
    ",ans);
    56 }
    View Code
  • 相关阅读:
    161012、JAVA读写文件,如何避免中文乱码
    161011、oracle批量插入数据
    161010、在大型项目中组织CSS
    160930、Javascript的垃圾回收机制与内存管理
    160929、各数据库连接配置与maven依赖安装
    Selenium学习(8) Cookie处理
    Selenium学习(7) 文件上传
    Selenium学习(6) 控制浏览器操作
    Selenium学习(5) 元素等待
    Selenium学习(4) 键盘操作
  • 原文地址:https://www.cnblogs.com/cychester/p/9478776.html
Copyright © 2020-2023  润新知