• SCOI2010 股票交易


    题目链接

    Solution

    动态规划题,设 (f_{i,j}) 表示前 (i) 天,手中有 (j) 股的最大钱数。分为 (4) 种情况讨论:

    凭空买入

    即在当日开始时手中没有股票,当日买入 (j) 股。转移方程:

    [f_{i,j}=-j * ap_i ]

    不买也不卖

    直接转移:

    [f_{i,j}=max(f_{i,j},f_{i-1,j}) ]

    从前面的某天买入

    观察情况 (2),发现 (f_{i,j}≥f_{i-1,j}),所以可以直接用第 (i-w-1) 天更新第 (i) 天,不用考虑前面。转移方程:

    [f_{i,j}=max(f_{i,j},f_{i-w-1}{k}-(k-j)*ap_i) (j-as_i≤k<j) ]

    从前面的某天卖出

    类似于情况 (3),转移方程为:

    [f_{i,j}=max(f_{i,j},f_{i-w+1}{k}+(j-k)*bp_i) (j<k≤j+bs_i) ]

    优化

    这样转移复杂度 (O(n^3)),难以通过 (2000) 的数据,考虑优化:

    以情况 (3) 把式子拆开:

    [f_{i,j}=max(f_{i,j},f_{i-w-1}{k}+k*ap_i-j*ap_i) ]

    (j) 提出来:

    [f_{i,j}=max(f_{i,j},f_{i-w-1,k}+k*ap_i)-j*ap_i ]

    于是就可以使用单调队列维护。情况 (4) 同理。

    Code

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    using namespace std;
     
    const int N = 3333;
    int ans = 0, t, maxp, w, head, tail;
    int ap[N], bp[N], as[N], bs[N], f[N][N], q[N], p[N];
     
    int main()
    {
        scanf("%d%d%d", &t, &maxp, &w);
        for(int i = 1; i <= t; i++)
            scanf("%d%d%d%d", &ap[i], &bp[i], &as[i], &bs[i]);
        memset(f, -0x3f, sizeof(f));
        for(int i = 1; i <= t; i++)
        {
            for(int j = 0; j <= as[i]; j++) f[i][j] = -j * ap[i];
            for(int j = 0; j <= maxp; j++) f[i][j] = max(f[i][j], f[i - 1][j]);
            if(i - w - 1 <= 0) continue;
            head = 1, tail = 0;
            for(int j = 1; j <= maxp; j++)
            {
                while(head <= tail && p[head] < j - as[i]) head++;
                while(head <= tail && q[tail] <= f[i - w - 1][j - 1] + (j - 1) * ap[i]) tail--;
                q[++tail] = f[i - w - 1][j - 1] + (j - 1) * ap[i], p[tail] = j - 1;
                f[i][j] = max(f[i][j], q[head] - j * ap[i]);
            }
            head = 1, tail = 0;
            for(int j = maxp - 1; j >= 0; j--)
            {
                while(head <= tail && p[head] > j + bs[i]) head++;
                while(head <= tail && q[tail] <= f[i - w - 1][j + 1] + (j + 1) * bp[i]) tail--;
                q[++tail] = f[i - w - 1][j + 1] + (j + 1) * bp[i], p[tail] = j + 1;
                f[i][j] = max(f[i][j], q[head] - j * bp[i]);
            }
        }
        for(int i = 0; i <= maxp; i++) ans = max(ans, f[t][i]);
        printf("%d", ans);
        return 0;
    }
    
  • 相关阅读:
    软件测试
    python学习之路
    好用的在线画图工具processon
    spring-boot集成dubbo
    公众号开放,关注软件开发过程中的哪些坑
    crontab 中curl命令无法正常执行
    近一月翻阅资料小结
    nginx+tomat8负载后,利用redis实现tomcat8的session共享
    centos7 安装nginx
    centos 上安装redis 3.0.5
  • 原文地址:https://www.cnblogs.com/Andy-park/p/12498017.html
Copyright © 2020-2023  润新知