• [SCOI2010]股票交易


    题目描述

    最近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


    现在单调队列都快忘了==

    写的详细点复习一下

    首先有一个肥肠显然的70pts的做法

    就是设f[i][j]表示第i天结束后还有j股

    然后分4种情况讨论一下

    sit1 : 啥也不干

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

    sit2 :i <= w + 1 天时买股票

    f[i][j] = - Ap[i] * j

    sit3 : 在 i > w + 1 天时买股票

    这时我们就从第 i - w - 1 天转移即可(因为sit1已经把前面的结果压到第i - w - 1天了)

    然后因为有买入上界的限制,所以 max(j-As[i]) <= k <= j

    f[i][j] = max(f[i][j] , f[i - w - 1][k] - (j - k) * Ap[i])

    sit4 : 在 i > w + 1 天时抛股票

    和sit3同理

    j <= k <= min(Maxp , j + Bs[i])

    f[i][j] = max(f[i][j] , f[i - w - 1][k] + (k - j) * Bp[i])

    这样就能得到一个n^3的暴力DP

    问题主要出在sit3和sit4

    我们考虑对sit3和sit4优化

    化简一下sit3和sit4的式子

    sit3 : f[i][j] = max(f[i][j] , f[i - w - 1][k] + k * Ap[i] - j * Ap[i])

    sit4 :f[i][j] = max(f[i][j] , f[i - w - 1][k] + k * Bp[i] - j * Bp[i])

    发现可以用单调队列维护使f[i - w - 1][k] + k * Ap[i]在合法的区间内能取得最大值的k

    还有就是要注意循环的顺序

    sit3要正着循环

    因为sit3的每个合法区间 j - As[i] ~ j 是 <=j 的

    所以新进来的元素顶掉的合法区间外的元素一定在后来进来的元素的合法区间之外

    sit4要倒着循环

    因为sit4的每个合法区间 j ~ j + Bs[i] 是 >= j 的

    与sit3同理

    这样复杂度就成n^2辣

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    const int M = 2005 ;
    using namespace std ;
    inline int read() {
        char c = getchar() ; int x = 0 , w = 1 ;
        while(c>'9'||c<'0') { if(c=='-') w = -1 ; c = getchar() ; }
        while(c>='0'&&c<='9') { x = x * 10+c-'0' ;c = getchar() ; }
        return x*w ;
    }
    int n , Maxp , w ;
    int Ap[M] , Bp[M] , As[M] , Bs[M] ;
    int f[M][M] ;
    int q[M] , head , tail ;
    int Ans ;
    int main() {
        n = read() ; Maxp = read() ; w = read() ;
        for(int i = 1 ; i <= n ; i ++) {
            Ap[i] = read() ; Bp[i] = read() ;
            As[i] = read() ; Bs[i] = read() ;
        }
        memset(f , -63 , sizeof(f)) ;
        for(int i = 1 ; i <= n ; i ++) {
        	
            for(int j = 1 ; 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) continue ;
            head = 1 , tail = 0 ;
            for(int j = 0 ; j <= Maxp ; j ++) {
            	while(head <= tail && q[head] < j - As[i]) ++head ;
    			while(head <= tail && 
    			f[i - w - 1][q[tail]] + q[tail] * Ap[i] <= f[i - w - 1][j] + j * Ap[i])
            	  tail-- ;
            	q[++tail] = j ;
            	if(head <= tail)
            	    f[i][j] = max(f[i][j] , f[i - w - 1][q[head]] + q[head] * Ap[i] - j * Ap[i]) ;
    		}
    		head = 1 , tail = 0 ;
    		for(int j = Maxp ; j >= 0 ; j --) {
    			while(head <= tail && q[head] > j + Bs[i]) 
    			    ++head ;
    			while(head <= tail && 
    			f[i - w - 1][q[tail]] + q[tail] * Bp[i] <= f[i - w - 1][j] + j * Bp[i])
    			  tail -- ;
    			q[++tail] = j ;
    			if(head <= tail)
    			    f[i][j] = max(f[i][j] , f[i - w - 1][q[head]] + q[head] * Bp[i] - j * Bp[i]) ;
    		}
    	}
    	for(int i = 0 ; i <= Maxp ; i ++) Ans = max(Ans , f[n][i]) ;
        printf("%d
    ",Ans) ;
        return 0 ;
    }
    
  • 相关阅读:
    PHP:使用Zend对源码加密、Zend Guard安装以及Zend Guard Run-time support missing的解决方法
    PHP:WampServer下如何安装多个版本的PHP、mysql、apache
    Windows7下无法打开chm(mk:@MSITStore:路径[cannot open the file mk@MSITstore:路径]),chm索引就关闭的解决办法
    C#:ListView控件如何实现点击列表头进行排序?
    C#:struct的陷阱:无法修改“xxx”的返回值,因为它不是变量
    C#:装箱和拆箱相关知识整理
    wifipineapple的evilportal
    mshta 反弹shell
    kali系统教程:创建热点
    office漏洞利用--获取shell
  • 原文地址:https://www.cnblogs.com/beretty/p/9532920.html
Copyright © 2020-2023  润新知