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

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

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

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

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

    输入输出格式

    输入数据第一行包括 33 个整数,分别是 (T)( ext{MaxP})(W)

    接下来 (T) 行,第 (i) 行代表第 (i-1)天的股票走势,每行 (4) 个整数,分别表示 (AP_i, BP_i, AS_i, BS_i)

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

    5 2 0
    2 1 1 1
    2 1 1 1
    3 2 1 1
    4 3 1 1
    5 4 1 1
    
    3
    

    说明

    对于 (30\%) 的数据,(0leq W<Tleq 50,1leq ext{MaxP}leq50)

    对于 (50\%) 的数据,(0leq W<Tleq 2000,1leq ext{MaxP}leq50)

    对于 (100\%) 的数据,(0leq W<Tleq 2000,1leq ext{MaxP}leq2000)

    对于所有的数据,(1leq BP_ileq AP_ileq 1000,1leq AS_i,BS_ileq ext{MaxP})


    这题真的难,写了我两个小时。(也可以等效于我是真的菜)

    不打算讨论题目的解题思路,就是单纯的讲一下这三天写单调队列的感受吧。

    • 刚看到一个题目不用刻意去想是不是单调队列。
    • 能用单调队列写的首先通常有一个复杂度爆炸的暴力。
    • 其形式通常为一个包含多变量的明确的状态方程,有的变量可能会非常大。
    • 单队特称明显,暴力转单调队列是自然而然的事情。
    • 一开始跳过暴力直接写正解,很容易导致正确性出现问题。(除非题目很简单)
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define MAXN 2010
    #define INF 0x7fffffff
    using namespace std;
    
    int h1,t1,h2,t2;
    int n,m,w,ans,AP[MAXN],BP[MAXN];
    int AS[MAXN],BS[MAXN],f[MAXN][MAXN];
    
    struct node{
        int nod,val;
    }q1[MAXN],q2[MAXN];
    
    int main(){
        cin>>n>>m>>w;
        for(register int i=1;i<=n;++i){
            cin>>AP[i]>>BP[i]>>AS[i]>>BS[i];
        }
        memset(f,-0x3f,sizeof(f));f[0][0]=0;
        for(register int i=1;i<=n;++i){//枚举当前哪一天 
            for(register int j=0;j<=m;++j){
                if(j<=AS[i]){//如果一次购买可以达到j股
                    f[i][j]=max(f[i][j],f[0][0]-AP[i]*j);
                }
                f[i][j]=max(f[i][j],f[i-1][j]);//不作购买 
            }
            h1=1,t1=0,h2=1,t2=0;
            for(register int j=1;j<=m;++j){
                if(i-w-1>0){
                    node ins;ins.nod=j-1;
                    ins.val=f[i-w-1][j-1]+AP[i]*(j-1);
                    while(h1<=t1 && q1[t1].val<=ins.val)t1--;
                    q1[++t1]=ins; 
                    while(h1<=t1 && q1[h1].nod<j-min(j,AS[i]))h1++;
                    f[i][j]=max(f[i][j],q1[h1].val-AP[i]*j);
                } 
            }
            for(register int j=m-1;j>=0;--j){
                if(i-w-1>0){
                    node ins;ins.nod=j+1;
                    ins.val=f[i-w-1][j+1]+BP[i]*(j+1);
                    while(h2<=t2 && q2[t2].val<=ins.val)t2--;
                    q2[++t2]=ins; 
                    while(h2<=t2 && q2[h2].nod>j+min(m-j,BS[i]))h2++;
                    f[i][j]=max(f[i][j],q2[h2].val-BP[i]*j);
                }
            }
        }
        for(register int i=1;i<=n;++i){
        	for(register int j=0;j<=m;++j){
        		ans=max(ans,f[i][j]);
    		}
    	}
        cout<<ans<<endl;
    } 
    
  • 相关阅读:
    WCF 转 武胜
    NET(C#):GetHashCode不需要太复杂 转 武胜
    wcf KnownTypeAttribute 武胜
    memmove
    李开复谈创业失败十原因:经不住诱惑 直接山寨
    Linux使用Wine 安装source insight
    VM 中ubuntu下Eclipse ctrl+s 显示update conflict的问题
    ISO/OSI模型
    memset函数使用详解
    C语言中字符串的处理方式
  • 原文地址:https://www.cnblogs.com/maomao9173/p/10046226.html
Copyright © 2011-2022 走看看