zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    A1052. Linked List Sorting (25)
    A1032. Sharing (25)
    A1022. Digital Library (30)
    A1071. Speech Patterns (25)
    A1054. The Dominant Color (20)
    A1060. Are They Equal (25)
    A1063. Set Similarity (25)
    电子码表
    矩阵键盘
    对象追踪、临时对象追踪、绝对坐标与相对坐标
  • 原文地址:https://www.cnblogs.com/cychester/p/9478776.html
Copyright © 2011-2022 走看看