• 洛谷 P2569[SCOI2010]股票交易(动规+单调队列)


    //只能写出裸的动规,为什么会有人能想到用单调队列优化Orz

    题目描述

    最近lxhgww又迷上了投资股票,通过一段时间的观察和学习,他总结出了股票行情的一些规律。

    通过一段时间的观察,lxhgww预测到了未来T天内某只股票的走势,第i天的股票买入价为每股APi,第i天的股票卖出价为每股BPi(数据保证对于每个i,都有APi>=BPi),但是每天不能无限制地交易,于是股票交易所规定第i天的一次买入至多只能购买ASi股,一次卖出至多只能卖出BSi股。

    另外,股票交易所还制定了两个规定。为了避免大家疯狂交易,股票交易所规定在两次交易(某一天的买入或者卖出均算是一次交易)之间,至少要间隔W天,也就是说如果在第i天发生了交易,那么从第i+1天到第i+W天,均不能发生交易。同时,为了避免垄断,股票交易所还规定在任何时间,一个人的手里的股票数不能超过MaxP。

    在第1天之前,lxhgww手里有一大笔钱(可以认为钱的数目无限),但是没有任何股票,当然,T天以后,lxhgww想要赚到最多的钱,聪明的程序员们,你们能帮助他吗?

    输入输出格式

    输入格式:

    输入数据第一行包括3个整数,分别是T,MaxP,W。

    接下来T行,第i行代表第i-1天的股票走势,每行4个整数,分别表示APi,BPi,ASi,BSi。

    输出格式:

    输出数据为一行,包括1个数字,表示lxhgww能赚到的最多的钱数。

    输入输出样例

    输入样例#1:
    5 2 0
    2 1 1 1
    2 1 1 1
    3 2 1 1
    4 3 1 1
    5 4 1 1
    
    输出样例#1:
    3

    说明

    对于30%的数据,0<=W<T<=50,1<=MaxP<=50

    对于50%的数据,0<=W<T<=2000,1<=MaxP<=50

    对于100%的数据,0<=W<T<=2000,1<=MaxP<=2000

    对于所有的数据,1<=BPi<=APi<=1000,1<=ASi,BSi<=MaxP

    题解:

    裸的方程:

    令每行四个数a,b,c,d

    方程f[i][j]表示第 i 天结束后,手里剩下 j 股的最大利润
    则 不买不卖:f[i][j]=f[i-1][j]
    买入: f[i][j]=max{f[i-w-1][k]-a[i]*(j-k)}(j-c[i]<=k<=j-1)
    卖出: f[i][j]=max{f[i-w-1][k]+b[i]*(k-j)}(j+1<=k<=j+d[i])

    正确的方法(迷之变形):

    买入:f[i][j]=max{f[i-w-1][k]+k*a[i]}-a[i]*j
    卖出:f[i][j]=max{f[i-w-1][k]+k*b[i]}-b[i]*j
    所以可以将括号里面的方程式压入单调队列

    此时复杂度降低为复杂度O(N*W)原来O(N*W*2)

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    #define man 2010
    int a[man],b[man],c[man],d[man],f[man][man],sta[man];
    int t,mp,w,hd,tl;
    int main()
    {
        cin>>t>>mp>>w;
        for(int i=1;i<=t;i++) cin>>a[i]>>b[i]>>c[i]>>d[i];
        memset(f,-127/3,sizeof(f));
        for(int i=0;i<=t;i++)f[i][0]=0;
        for(int i=1;i<=t;i++)
        {
            for(int j=0;j<=c[i];j++)f[i][j]=-a[i]*j;
            for(int j=mp;j>=0;j--)f[i][j]=max(f[i][j],f[i-1][j]);
            if(i-w-1>=0)
            {
                hd=1;tl=0;
                for(int j=0;j<=mp;j++)
                {
                    while(hd<=tl&&sta[hd]<j-c[i])hd++;
                    while(hd<=tl&&f[i-w-1][j]+a[i]*j>=f[i-w-1][sta[tl]]+a[i]*sta[tl])tl--;
                    sta[++tl]=j;
                    if(hd<=tl)
                    f[i][j]=max(f[i][j],f[i-w-1][sta[hd]]-a[i]*(j-sta[hd]));
                    }
                hd=1;tl=0;
                for(int j=mp;j>=0;j--)
                {
                    while(hd<=tl&&sta[hd]>j+d[i])hd++;
                    while(hd<=tl&&f[i-w-1][j]+b[i]*j>=f[i-w-1][sta[tl]]+b[i]*sta[tl])tl--;
                    sta[++tl]=j;
                    if(hd<=tl)
                    f[i][j]=max(f[i][j],f[i-w-1][sta[hd]]+b[i]*(sta[hd]-j));
                    }
                    }
            }
        int ans=0;
        for(int i=0;i<=mp;i++)ans=max(ans,f[t][i]);
        cout<<ans<<endl;
        }

    话说,为什么大家的题解几乎都是一样的。。(我也是看别人的。。。)

  • 相关阅读:
    MyBatisPlus简单查询
    vue Composition API官网
    操作mysql脚本
    elbutton 自定义背景图片
    k8s 应用yaml
    分页查询
    nodejs 工具库
    eltablecolumn的转义,eltablecolumn根据返回的数据判断
    谷歌地图在线
    YOLOX在OpenVINO、ONNXRUNTIME、TensorRT上面推理部署与速度比较
  • 原文地址:https://www.cnblogs.com/Slager-Z/p/7766301.html
Copyright © 2020-2023  润新知