zoukankan      html  css  js  c++  java
  • luogu P2569 [SCOI2010]股票交易 单调优化dp

    参考:https://www.luogu.com.cn/blog/Sooke/solution-p2569

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    using namespace std;
    const int N=2001;
    int n,m,w;
    int ap,bp,as,bs;
    int ans;
    int f[N][N] ;// f[i][j] 表示第 i 天后拥有 j 张股票赚的最多钱数
    int hh,tt,q[2001];
    int main()
    {
    	cin>>n>>m>>w;
    	memset(f,128,sizeof f); // 128 实际上给 f 数组赋的是 -inf,可以试试看
    	for(int i=1;i<=n;i++)
    	{
    		//买入价格,卖出价格,最多买,最多卖
    		cin>>ap>>bp>>as>>bs;
    		for(int j=0;j<=as;j++)
    			f[i][j]=-1*j*ap; //凭空买
    		for(int j=0;j<=m;j++)
    			f[i][j]=max(f[i][j],f[i-1][j]); // 不买也不卖
    		if(i<=w)//如果小于天数,就不能卖
    			continue; // 因为第 3,4 种情况都有 i - w - 1,如果 i <= w,会出现负下标
    		//在之前的基础上买
    		hh=1,tt=1; // 单调队列准备
    		for(int j=0;j<=m;j++)
    		{
    			while(hh<tt&&q[hh]<j-as)
    				hh++;
    			while(hh<tt&&f[i-w-1][q[tt-1]]+q[tt-1]*ap<=f[i-w-1][j]+j*ap)
    				tt--;
    			q[tt++]=j;
    			if(hh<tt)
    				f[i][j]=max(f[i][j],f[i-w-1][q[hh]]+q[hh]*ap-j*ap);
    		}
    		//在之前的基础上卖
    		hh=1,tt=1;
    		for(int j=m;j>=0;j--)
    		{
    			while(hh<tt&&q[hh]>j+bs)
    				hh++;
    			while(hh<tt&&f[i-w-1][q[tt-1]]+q[tt-1]*bp<=f[i-w-1][j]+j*bp)
    				tt--;
    			q[tt++]=j;
    			if(hh<tt)
    				f[i][j]=max(f[i][j],f[i-w-1][q[hh]]+q[hh]*bp-j*bp);
    		}
    	}
    	for(int i=0;i<=m;i++)
    		ans=max(ans,f[n][i]);
    	cout<<ans<<endl;
    	return 0;
    }
    
  • 相关阅读:
    排球教练积分程序
    排球积分程序
    排球积分程序
    14周总结
    本周总结
    排球计分规则
    我与计算机
    排球计分程序
    《如何成为一个高手》观后感
    十八周总结
  • 原文地址:https://www.cnblogs.com/QingyuYYYYY/p/12916135.html
Copyright © 2011-2022 走看看