zoukankan      html  css  js  c++  java
  • 股票交易

    https://loj.ac/problem/10183

    题目描述

      已知股票(T)天的买入价和卖出价, 以及每天最多购买数和最多卖出数,并规定两次交易之间至少间隔(W)天,同一时间一个人的股票数不能超过(MaxP),求最多的获利。

    思路

      这道题的限制条件比较多,但我们可以简单梳理出(dp)的模型,由于最多股票数已经给出,所以我们可以定义(f[i][j])为到第(i)天为止有(j)支股票的最大获利。那么对于当前的状态来说,它可能有四种情况转移过来:1、全部在这一天买入;2、这一天买入(k)股并在(i-w-1)天有(j-k)股;3、这一天卖出(k)股,在(i-w-1)天有(j+k)股。4、这一天什么也没干。这样就很好转移了,不过考虑暴力转移复杂度会炸掉,但由于枚举的股数之间有状态的重叠,所以我们可以维护买入中在限额内的最大值,用单调队列维护即可。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    const int N=2200;
    
    int read()
    {
    	int res=0,w=1;
    	char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){res=(res<<3)+(res<<1)+(ch^48);ch=getchar();}
    	return res*w;
    }
    
    int q[N],ap[N],bp[N],as[N],bs[N];
    int f[N][N];
    int main()
    {
    	int t,maxp,w;
    	t=read();maxp=read();w=read();
    	for(int i=1;i<=t;i++)
    		ap[i]=read(),bp[i]=read(),as[i]=read(),bs[i]=read();
    	memset(f,-0x3f,sizeof(f));
    	f[0][0]=0;
    	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 ;
    		
    		int head=1,tail=0,v=i-w-1;
    		for(int j=0;j<=maxp;j++)
    		{
    			while(head<=tail&&q[head]<j-as[i])head++;
    			while(head<=tail&&f[v][q[tail]]+q[tail]*ap[i]<=f[v][j]+j*ap[i])tail--;
    			q[++tail]=j;
    			f[i][j]=max(f[i][j],f[v][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[v][q[tail]]+q[tail]*bp[i]<=f[v][j]+j*bp[i])tail--;
    			q[++tail]=j;
    			f[i][j]=max(f[i][j],f[v][q[head]]+q[head]*bp[i]-j*bp[i]);
    		}
    	}
    	int ans=0;
    	for(int i=0;i<=maxp;i++)
    		ans=max(ans,f[t][i]);
    	printf("%d
    ",ans);
    }
    /*
    单买:f[i][j]=-j*ap[i]; 
    买:f[i][j]=max(f[i][j],f[i-w-1][k]-(j-k)*ap[i-w-1])  j-as[i]=<k<j 
    卖:f[i][j]=max(f[i][j],f[i-w-1][k]+(k-j)*bp[i-w-1])  j<k<=j+bs[i]
    none: f[i][j]=max(f[i][j],f[i-1][j])
    */
    
  • 相关阅读:
    web前端开发面试被虐篇(一)
    JSON字符串 拼接与解析
    IntelliJ IDEA 2017 Dubbo Elastic-job Redis Zookeeper RabbitMQ FastDFS MyCat 简介以及部分实现(三)
    IntelliJ IDEA 2017 MySQL5 绿色版 Spring 4 Mybatis 3 配置步骤详解(二)
    IntelliJ IDEA 2017 JDK Tomcat Maven 配置步骤详解(一)
    简单练习
    C#实现上传/下载Excel文档
    javascript练习题
    转 浏览器滚动条以及常用样式汇总
    深入基础(五)工具模块,常用模块(2)
  • 原文地址:https://www.cnblogs.com/fangbozhen/p/11852130.html
Copyright © 2011-2022 走看看