Mayflyyh
Mayflyyh
MayFlyyh's Blog
Luogu P2569 [SCOI2010]股票交易

[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想要赚到最多的钱,聪明的程序员们,你们能帮助他吗?

对于30%的数据,0 < =W 对于50%的数据,0 < =W 对于100%的数据,0 < =W

对于所有的数据,1 < =BPi < =APi < =1000,1 < =ASi,BSi < =MaxP


3次方裸状态转移

#include<bits/stdc++.h>
#define ll long long
const int N = 3000;
int n;ll dp[N][N],maxp;int w;
int main(){
    scanf("%d%lld%d",&n,&maxp,&w);
    memset(dp,-0x3f,sizeof(dp));
    dp[0][0]=0;
    for(int i=1;i<=n;++i){
        ll ap,bp,as,bs;
        scanf("%lld %lld %lld %lld",&ap,&bp,&as,&bs);
        for(int j=0;j<=maxp;++j){
            for(int k=0;k<=j&&k<=bs;++k){
                dp[i][j-k]=std::max(dp[i][j-k],dp[std::max(0,i-w-1)][j]+k*bp);
            }
            for(int k=0;j+k<=maxp&&k<=as;++k){
                dp[i][j+k]=std::max(dp[i][j+k],dp[std::max(0,i-w-1)][j]-k*ap);
            }
        }
        for(int j=0;j<=maxp;++j)
            dp[i][j]=std::max(dp[i][j],dp[i-1][j]);
    }
    ll ans=0;
    for(int i=0;i<=maxp;++i)
        ans=std::max(ans,dp[n][i]);
    printf("%lld\n",ans);
    return 0;
} 

卖出: dp[i][j]=max(dp[i][j],dp[i-w-1][k]+(k-j)*bp);(k>j)

买入: dp[i][j]=max(dp[i][j],dp[i-w-1][k]-(j-k)*ap);(k

然后拆开发现

dp[i-w-1][k]-j*ap+k*ap

dp[i-w-1][k]+k*ap-j*ap

发现大小仅与k有关,又因为有bs、as限制,进单调队列即可

//GG
#include<bits/stdc++.h> 
#define ll long long 
int t,maxp,w;
const int N = 2010;
ll dp[N][N],ans;
int Q[N],hd,tl;
int main(){
    //freopen("trade.in","r",stdin);
    //freopen("trade.out","w",stdout);
    scanf("%d %d %d",&t,&maxp,&w);
    memset(dp,-0x3f,sizeof(dp));
    dp[0][0]=0;
    for(int i=1;i<=t;++i){
        ll ap,bp,as,bs;
        scanf("%lld %lld %lld %lld",&ap,&bp,&as,&bs);
        int wh=std::max(0,i-w-1);
        hd=1,tl=0;
        for(int j=0;j<=maxp;++j){
            while(hd<=tl&&Q[hd]<j-as) 
                hd++;
            while(hd<=tl&&dp[wh][Q[tl]]+1ll*Q[tl]*ap<=dp[wh][j]+1ll*j*ap) 
                tl--;
            Q[++tl]=j;
            dp[i][j]=std::max(dp[i][j],dp[wh][Q[hd]]+Q[hd]*ap-j*ap);
            /*
                dp[i][k]=dp[wh][j]+j*ap-k*ap
            */
        }
        hd=1,tl=0;
        for(int j=maxp;j+1;--j){
            while(hd<=tl&&Q[hd]>j+bs)
                hd++;
            while(hd<=tl&&dp[wh][Q[tl]]+1ll*Q[tl]*bp<=dp[wh][j]+1ll*j*bp)
                tl--;
            Q[++tl]=j;
            dp[i][j]=std::max(dp[i][j],dp[wh][Q[hd]]+(Q[hd]-j)*bp);
            /*
                dp[i][k]=dp[wh][j]+j*bp-k*bp
            */
            }
        for(int j=0;j<=maxp;++j){
            dp[i][j]=std::max(dp[i][j],dp[i-1][j]);
            ans=std::max(ans,dp[i][j]);
            //printf("dp[%d][%d]=%d\n",i,j,dp[i][j]);
        }
    }
    printf("%lld",ans);
    return 0;
}
本文链接:http://www.mayflyyh.com/archives/449
知识共享许可协议
本文采用CC BY-NC-SA 3.0进行许可。
没有标签
首页      DP      Luogu P2569 [SCOI2010]股票交易
http://0.gravatar.com/avatar/6cc3a2831375e487976e09c80dfcb52e?s=256&d=monsterid&r=g

MayFlyyh

文章作者

Oier

发表评论

textsms
account_circle
email

MayFlyyh's Blog

Luogu P2569 [SCOI2010]股票交易
[SCOI2010]股票交易 最近lxhgww又迷上了投资股票,通过一段时间的观察和学习,他总结出了股票行情的一些规律。 通过一段时间的观察,lxhgww预测到了未来T天内某只股票的走势,第i天的…
扫描二维码继续阅读
2018-12-19