[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<j)
然后拆开发现
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;
}
0 条评论