[bzoj1855][Scoi2010]股票交易_动态规划_单调队列
股票交易 bzoj-1855 Scoi-2010
题目大意:说不明白题意系列++...题目链接
注释:略。
想法:这个题还是挺难的。
动态规划没跑了
状态:dp[i][j]表示第i天手里有j个股票的最大获利。
转移:第i天可以选择搞事情或者什么都不干。
如果不买不卖的话,有dp[i][j]=dp[i-1][j]
如果选择买入,dp[i][j]=dp[i-w-1][k]-ap[i](j-k)|k>=j-as[i]
如果选择卖出,dp[i][j]=dp[i-w-1][k]+bp[i](k-j)|k<=j+bs[i].
然后,我们以k为时间戳信息,dp[i-w-1][k]+ap[i][k]为权值信息维护单调队列(以买入为例)即可。
最后,附上丑陋的代码... ...
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define N 2010 using namespace std; int t,maxp,w; int f[N][N]; int q[N]; struct node { int ap,bp,as,bs; }a[N]; int main() { scanf("%d%d%d",&t,&maxp,&w); for(int i=1;i<=t;i++) { scanf("%d%d%d%d",&a[i].ap,&a[i].bp,&a[i].as,&a[i].bs); } memset(f,-0x3f,sizeof(f)); for(int i=1;i<=t;i++) { for(int j=0;j<=a[i].as;j++) f[i][j]=-a[i].ap*j; for(int j=0;j<=maxp;j++) f[i][j]=max(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&&q[head]<j-a[i].as)head++; while(head<tail&&f[i-w-1][j]+j*a[i].ap>=f[i-w-1][q[tail-1]]+q[tail-1]*a[i].ap)tail--; q[tail++]=j; if(head<tail)f[i][j]=max(f[i][j],f[i-w-1][q[head]]-(j-q[head])*a[i].ap); } head=0,tail=0; for(int j=maxp;j>=0;j--) { while(head<tail&&q[head]>j+a[i].bs)head++; while(head<tail&&f[i-w-1][j]+j*a[i].bp>=f[i-w-1][q[tail-1]]+q[tail-1]*a[i].bp)tail--; q[tail++]=j; if(head<tail)f[i][j]=max(f[i][j],f[i-w-1][q[head]]+(q[head]-j)*a[i].bp); } } } int ans=0; for(int i=0;i<=maxp;i++) { ans=max(ans,f[t][i]); } printf("%d\n",ans); }
小结: 单调队列好有意思...
| 欢迎来原网站坐坐! >原文链接<