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

    题目链接

    Solution [SCOI2010]股票交易

    题目大意:给定(n)天,每一天有股票买入价格(AP_i),买入限制(AS_i),卖出价格(BP_i),卖出限制(BS_i),每次交易后需间隔至少(w)天(含(w)),手中股票数量不得大于(MaxP),求最大收益

    动态规划,单调队列


    分析:我们很快就可以列出一个(O(n^3))的朴素(dp)

    (f[i][j])表示到(i)天为止,在第(i)天时手中有(j)张股票的最大收益,然后分类讨论

    • (1.)无中生有(),之前啥都不干然后在(i)天购买股票:

    (f[i][j] = max(f[i][j],-j imes AP_i) quad j in [0,AS_i])

    • (2.)啥都不干

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

    • (3.)买股票

    (f[i][j] = max(f[i][j],f[i - w - 1][k]-(j-k) imes AP_i) quad i > w,k in [max(0,j - AS_i),j])

    • (4.)卖股票

    (f[i][j] = max(f[i][j],f[i - w - 1][k]+(k-j) imes BP_i) quad i > w,k in[j,min(MaxP,j+BS_i)])

    我们买卖股票的时候不需要枚举最优最测点的(i)(也就是天数),因为它们都被(i-w-1)天计算过了

    然后状态(n^2)多半没法继续优化了,我们考虑从(O(n))转移下手

    我们先拆式子,把和决策点相关的部分和跟状态相关的部分分开
    (f[i - w - 1][k]-(j-k) imes AP_i=f[i - w - 1][k] + k imes AP_i-j imes AP_i)

    (f[i - w - 1][k]+(k-j) imes BP_i=f[i - w - 1][k] + k imes BP_i-j imes BP_i)

    后面和状态有关的常数项暂时忽略,首先,对于一个状态(f[i][j]),它的决策点的(i)是固定为(i-w-1)的,然后我们看(k)的取值范围,如果忽略掉上下界的话就是滑动窗口问题,于是我们可以对于每个(i)预处理出当前时刻(i)所有(j)的最优决策

    复杂度(O(n^2))

    #include <cstdio>
    #include <cctype>
    #include <algorithm>
    using namespace std;
    const int maxn = 2048;
    inline int read(){
        int x = 0;char c = getchar();
        while(!isdigit(c))c = getchar();
        while(isdigit(c))x = x * 10 + c - '0',c = getchar();
        return x;
    }
    int val[2][maxn],q[maxn],ans[2][maxn],f[maxn][maxn],AP[maxn],AS[maxn],BP[maxn],BS[maxn],n,maxp,w,head,tail;
    inline void solve(int tim){
        for(int k = 0;k <= maxp;k++)
            val[0][k + 1] = f[tim - w - 1][k] + k * AP[tim],val[1][k + 1] = f[tim - w - 1][k] + k * BP[tim],ans[0][k] = ans[1][k] = -0x7fffffff;
        head = 1,tail = q[0] = 0;
        for(int i = 1;i <= maxp + 1;i++){
            while(head <= tail && val[0][q[tail]] <= val[0][i])tail--;
            q[++tail] = i;
            while(head <= tail && q[head] < i - AS[tim])head++;
            if(head <= tail)ans[0][i - 1] = val[0][q[head]];
        }
        head = 1,tail = q[0] = 0;
        for(int i = maxp + 1;i >= 1;i--){
            while(head <= tail && val[1][q[tail]] <= val[1][i])tail--;
            q[++tail] = i;
            while(head <= tail && q[head] > i + BS[tim])head++;
            if(head <= tail)ans[1][i - 1] = val[1][q[head]];
        }
    }
    int main(){
        scanf("%d %d %d",&n,&maxp,&w);
        for(int i = 1;i <= n;i++)
            scanf("%d %d %d %d",AP + i,BP + i,AS + i,BS + i);
        for(int i = 1;i <= maxp;i++)f[0][i] = -0x3f3f3f3f;//这里注意,避免不合法状态
        for(int i = 1;i <= n;i++){
            if(i > w)solve(i);
            for(int j = 0;j <= maxp;j++){
                if(j <= AS[i])f[i][j] = -j * AP[i];
                else f[i][j] = -0x3f3f3f3f;
                f[i][j] = max(f[i][j],f[i - 1][j]);
                if(i > w)f[i][j] = max(f[i][j],ans[0][j] - j * AP[i]);
                if(i > w)f[i][j] = max(f[i][j],ans[1][j] - j * BP[i]);
            }
        }
        int ans = 0;
        for(int i = 0;i <= maxp;i++)ans = max(ans,f[n][i]);
        printf("%d
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    Django U2 模型
    Django U0 使用Django
    Django H2 文档查看
    python模块--time模块/os模块/sys模块
    python模块-logging和collections以及random模块
    python-hashlib模块configparser模块logging模块
    python模块--序列化
    python面向对象的特殊方法和单例模式
    python类属性和类方法以及静态方法和反射
    python面向对象的三个特性
  • 原文地址:https://www.cnblogs.com/colazcy/p/11693346.html
Copyright © 2011-2022 走看看