【BZOJ1855】股票交易

                                         1855: [Scoi2010]股票交易

                                                                         Time Limit: 5 Sec  Memory Limit: 64 MB
                                                                                    Submit: 1519  Solved: 792

Description

最近lxhgww又迷上了投资股票,通过一段时间的观察和学习,他总结出了股票行情的一些规律。 通过一段时间的观察,lxhgww预测到了未来T天内某只股票的走势,第i天的股票买入价为每股APi,第i天的股票卖出价为每股BPi(数据保证对于每个i,都有APi>=BPi),但是每天不能无限制地交易,于是股票交易所规定第i天的一次买入至多只能购买ASi股,一次卖出至多只能卖出BSi股。 另外,股票交易所还制定了两个规定。为了避免大家疯狂交易,股票交易所规定在两次交易(某一天的买入或者卖出均算是一次交易)之间,至少要间隔W天,也就是说如果在第i天发生了交易,那么从第i+1天到第i+W天,均不能发生交易。同时,为了避免垄断,股票交易所还规定在任何时间,一个人的手里的股票数不能超过MaxP。 在第1天之前,lxhgww手里有一大笔钱(可以认为钱的数目无限),但是没有任何股票,当然,T天以后,lxhgww想要赚到最多的钱,聪明的程序员们,你们能帮助他吗?

Input

输入数据第一行包括3个整数,分别是T,MaxP,W。 接下来T行,第i行代表第i-1天的股票走势,每行4个整数,分别表示APi,BPi,ASi,BSi。

Output

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

Sample Input

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

Sample Output

3

HINT

对于30%的数据,0 < =W 对于50%的数据,0 < =W 对于100%的数据,0 < =W 
对于所有的数据,1 < =BPi < =APi < =1000,1 < =ASi,BSi < =MaxP
 

 

解析:

       明显是一道DP题,不难列出DP方程:

对于买入的情况

由于dp[i][j]=max{ f [ i - w - 1][ k ] + k * ap [ i ] - j * Ap [ i ]}

AP[i]*j是固定的,在队列中维护dp[i-w-1][k]+k*Ap[i]的单调性即可。

代码:

#include <bits/stdc++.h>
using namespace std;
 
const int Max=2010;
int n,m,ans,maxp,w;
int f[Max][Max],ap[Max],bp[Max],as[Max],bs[Max],p[Max<<3];
 
inline int get_int()
{
    int x=0,f=1;
    char c;
    for(c=getchar();(!isdigit(c))&&(c!='-');c=getchar());
    if(c == '-') f=-1,c=getchar();
    for(;isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+c-'0';
    return x*f;
}
inline int mx(int x,int y){return x > y ? x : y;}
 
int main()
{
    n=get_int(),maxp=get_int(),w=get_int();
    for(int i=1;i<=n;i++) ap[i]=get_int(),bp[i]=get_int(),as[i]=get_int(),bs[i]=get_int();
    memset(f,-0x3f,sizeof(f));
    for(int i=1;i<=n;i++)
    {
      for(int j=0;j<=as[i];j++) f[i][j] = -ap[i] * j;
      for(int j=0;j<=maxp;j++) f[i][j] = mx(f[i][j] , f[i-1][j]);
      if(i-w-1 >= 0)
      {
        int head=0,tail=0;
        for(int j=0;j<=maxp;j++)
        {
          while(head < tail && p[head] + as[i] < j) head++;
          while(head < tail && f[i-w-1][p[tail-1]] + ap[i]*p[tail-1] <= f[i-w-1][j] + ap[i]*j) tail--;
          p[tail++] = j;
          f[i][j] = mx(f[i][j] , f[i-w-1][p[head]] - (j-p[head]) * ap[i]);
        }
        head=0,tail=0;
        for(int j=maxp;j>=0;j--)
        {
          while(head < tail && p[head] - bs[i] > j) head++;
          while(head < tail && f[i-w-1][p[tail-1]] + bp[i]*p[tail-1] <= f[i-w-1][j] + bp[i]*j) tail--;
          p[tail++] = j;
          f[i][j] = mx(f[i][j] , f[i-w-1][p[head]] + (p[head]-j) * bp[i]);
        }
      }
    }
 
    cout<<f[n][0]<<"\n";
    return 0;
}

猜你喜欢

转载自blog.csdn.net/m0_38083668/article/details/81408034