zoukankan      html  css  js  c++  java
  • P2569 [SCOI2010]股票交易

    P2569 [SCOI2010]股票交易

    题目链接

    数据结构优化DP。

    ​ 用(f[i][j])表示第(i)天手里还有(j)张股票的最大收益。

    ​ 分四种情况转移:

    ​ 直接买入,不承接之前的:

    f[i][j] = -ap * j;
    

    ​ 不卖也不买:

    f[i][j] = std::max(f[i][j], f[i - 1][j]);
    

    ​ 卖出股票:

    f[i][j] = std::max(f[i][j], f[i - w - 1][k] + (k - j) * bp);
    

    ​ 买入股票,承接之前的:

    f[i][j] = std::max(f[i][j], f[i - w - 1][k] - (j - k) * ap);
    

    ​ 为啥只能从(i - w - 1)转移过来呢?因为(i - w - 1)可能是从更前面转移过来的,比如说(i - w - 2),这样(i)其实也是从(i - w - 2)转移过来的。

    ​ 可以发现,第三种和第四种情况可以把(j)提出来:

    f[i][j] = max(f[i][j], std::max(f[i - w - 1][k] + k * bp) - j * bp);
    f[i][j] = max(f[i][j], std::max(f[i - w - 1][k] + k * ap) - j * ap);
    

    ​ 这样我们就可以用单调队列优化了,可以把(f[i - w - 1][k] + k * bp/ap)放入单调队列里,每次(O(1))找到最大值,总复杂度(O(n^2))

    #include <bits/stdc++.h>
    
    inline long long read() {
        long long s = 0, f = 1; char ch;
        while(!isdigit(ch = getchar())) (ch == '-') && (f = -f);
        for(s = ch ^ 48;isdigit(ch = getchar()); s = (s << 1) + (s << 3) + (ch ^ 48));
        return s * f;
    }
    
    const int N = 2005;
    int T, P, w, l, r, ap, bp, as, bs, ans;
    int p[N], f[N][N];
    
    int main() {
    
        T = read(); P = read(); w = read();
        
        memset(f, -0x3f, sizeof(f));
    
        for(int i = 1;i <= T; i++) {
    
            ap = read(), bp = read(), as = read(), bs = read();
    
            for(int j = 0;j <= as; j++) f[i][j] = -ap * j;
    
            for(int j = 0;j <= P; j++) f[i][j] = std::max(f[i][j], f[i - 1][j]);
            
            if(i <= w) continue;
    
            l = 1, r = 0;
            for(int j = P;j >= 0; j--) {
                while(l <= r && p[l] > j + bs) l++;
                // std::cout << l << std::endl;
                while(l <= r && f[i - w - 1][p[r]] + p[r] * bp <= f[i - w - 1][j] + j * bp) r--;
                p[++r] = j;
                if(l <= r) f[i][j] = std::max(f[i][j], f[i - w - 1][p[l]] + p[l] * bp - j * bp);
            }
    
            l = 1, r = 0;
            for(int j = 0;j <= P; j++) {
                while(l <= r && p[l] < j - as) l++;
                while(l <= r && f[i - w - 1][p[r]] + p[r] * ap <= f[i - w - 1][j] + j * ap) r--;
                p[++r] = j;
                if(l <= r) f[i][j] = std::max(f[i][j], f[i - w - 1][p[l]] + p[l] * ap - j * ap);
            }
        }
    
        for(int i = 0;i <= P; i++) ans = std::max(ans, f[T][i]);
    
        printf("%d", ans);
        
        return 0;
    }
    
  • 相关阅读:
    ecmall 开发一个新模块
    ecmall 如何新增挂件
    ecmall 主从表的4种模型关系
    ecmall 的一些方法说明
    ecmall 支付成功 订单状态没有改变解决办法
    ecmall 基础类分析
    phpcms 新建模块安装
    phpcms pc_base::load
    strptime()方法
    GDB调试方法精粹
  • 原文地址:https://www.cnblogs.com/czhui666/p/13655600.html
Copyright © 2011-2022 走看看