zoukankan      html  css  js  c++  java
  • 【题解】[SCOI2010]股票交易

    十分普通的DP+不平凡的转移

    传送门

    这道题状态十分明显。转移是(O(n^4))的,过不去,我们需要优化。

    一个十分显然的DP是(f(i,j))表示第(i)天时候拥有(j)单位股票的最大收益。(可以小于零)。它的转移方式是:

    (f(i,j)=max(f(k,b)+(b-j) imes sell[t] or(buy[t])))

    此时,我们发现一个转移需要两重循环,也就是(O(n^2)),加上右边的式子,就是(O(n^4))的。

    考虑优化:

    • 对于转移方程,发现我们可以进行参变量分离。对状态转移方程进行代数变形。

      • (RHS=max(f(k,b)+b imes sell[t]-j imes sell[t]))
      • (j)在转移时,是最开始那个等式的(LHS),可以提前确定,从(max)拿出来。
      • (RHS=max(f(k,b)+b imes sell[t])-j imes sell[t])
      • 于是,对于(max(f(k,b)+b imes sell[t])),可以拿数据结构维护了。
    • 对于转移方法,我们只需要(f(i-W-1,j) , jle maxP)转移过来就好了。这一定是最优的那个状态,比它要早的状态一定会$le f(i-W-1,j) $。

      • 因为这个(晚的)状态在转移的时候,考虑过 从比他 (早的) 状态直接转移过来,于是(f(i-W-1,j))不小于前面那个。

    于是,我们可以将(f(i-W-1,b) ,ble maxP)的所有状态压入某个数据结构。我们发现,对于这种数据结构的要求是:

    • 维护最大值
    • 可以清理过期状态(买入卖出股票有多少限制)
    • 重置方便

    就是单调队列吃饭的本领。

    一句话解释单调队列:一个状态比你小(限制条件少)还比你强(数值大),那么你就被淘汰了。

    单调队列是(O(n))的,枚举(LHS)(i)(O(n))的。总复杂度(O(n^2)),可以过了。


    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<cstdio>
    #include<queue>
    #include<bitset>
    #include<vector>
    #include<map>
    #include<ctime>
    #include<cstdlib>
    #include<set>
    #include<bitset>
    #include<stack>
    #include<list>
    #include<cmath>
    using namespace std;
    #define RP(t,a,b) for(register ll (t)=(a),edd_=(b);t<=edd_;++t)
    #define DRP(t,a,b) for(register ll (t)=(a),edd_=(b);t>=edd_;--t)
    #define ERP(t,a) for(int t=head[a];t;t=e[t].to)
    #define Min(a,b) ((a)<(b)?(a):(b))
    #define TMP template<class ccf>
    typedef long long ll;
    TMP inline ccf qr(ccf k){
       char c=getchar();
       ccf x=0;
       int q=1;
       while(c<48||c>57)
       q=c==45?-1:q,c=getchar();
       while(c>=48&&c<=57)
       x=x*10+c-48,c=getchar();
       if(q==-1)
       x=-x;
       return x;
    }
    const int maxn=2e3+15;
    inline void Swap(ll& a,ll& b){
       ll k=a;
       a=b;
       b=k;
    }
    
    ll buy[maxn];
    ll sell[maxn];
    ll buytimes[maxn];
    ll selltimes[maxn];
    ll n,maxP,W;
    ll dp[maxn][maxn];
    int q[maxn];
    
    TMP inline ccf Max(ccf a,ccf b){
       if(a<b)
       return b;
       return a;
    }
    
    
    
    inline void init(){
       memset(dp,-0xf,sizeof dp);
       RP(t,1,n){
       buy[t]=qr(1ll);
       sell[t]=qr(1ll);
       buytimes[t]=qr(1ll);
       selltimes[t]=qr(1ll);
       }
       RP(t,1,n){
       int head=1,tail=0;
       if(t-W-1>0){
           
           //trade
           DRP(i,maxP,0){
       	while(head<=tail&&q[head]>i+selltimes[t])
       	    head++;
       	while(head<=tail&&
       	      dp[t-W-1][q[tail]]+1ll*q[tail]*sell[t]
       	      <=dp[t-W-1][i]+1ll*i*sell[t]
       	      )
       	    --tail;
       	q[++tail]=i;
       	if(head<=tail)
       	    dp[t][i]=max(dp[t][i],dp[t-W-1][q[head]]+(q[head]-i)*sell[t]*1ll);
           }
    
           //purchase
           head=1,tail=0;
           RP(i,0,maxP){
       	while(head<=tail&&q[head]<i-buytimes[t])
       	    ++head;
       	while(head<=tail&&
       	      dp[t-W-1][q[tail]]+q[tail]*buy[t]
       	      <=dp[t-W-1][i]+i*buy[t])
       	    --tail;
       	q[++tail]=i;
       	if(head<=tail)
       	    dp[t][i]=Max(dp[t][i],dp[t-W-1][q[head]]+(q[head]-i)*buy[t]*1ll);
           }
       }
    
       //restart
       RP(i,0,maxP){
           dp[t][i]=Max(dp[t][i],dp[t-1][i]);
           if(i<=buytimes[t])
       	dp[t][i]=Max(dp[t][i],-i*buy[t]);
       }
       
       }
       ll ans=0;
       RP(t,0,maxP)
       ans=max(ans,dp[n][t]);
       cout<<ans<<endl;
       
    }
    
    
    
    int main(){
    #ifndef ONLINE_JUDGE
       freopen("in.in","r",stdin);
       freopen("out.out","w",stdout);
    #endif
       while(~scanf("%lld%lld%lld",&n,&maxP,&W))
       init();
       return 0;
    }
    
    
    
    
  • 相关阅读:
    Dungeon Game 解答
    Gray Code 解答
    N-Queens II 解答
    N-Queens 解答
    Permutation Sequence 解答
    Generate Parentheses 解答
    Letter Combinations of a Phone Number 解答
    Permutations 解答
    Combination Sum II 解答
    134. Gas Station
  • 原文地址:https://www.cnblogs.com/winlere/p/10307970.html
Copyright © 2011-2022 走看看