TradeTime Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Problem Description Recently, lxhgww is addicted to stock, he finds some Before the first day, lxhgww already has infinitely Input The first line is an integer t, the case number. Output The most money lxhgww can earn. Sample Input 1 Sample Output 3 Author lxhgww Source HDOJ Recommend lcy | We have carefully selected several similar |
|||
|
题目大意:知道之后n天的股票买卖价格(api,bpi),以及每天股票买卖数量上限(asi,bsi),问他最多能赚多少钱。开始时有无限本金,要求任两次交易需要间隔W天以上,即第i天交易,第i+w+1天才能再交易。同时他任意时刻最多只能拥有maxp的股票,
/* 1. dp[i][j] 表示前 i 天手里有 j 支股票时所获得的最大收益,因为要间隔 w+1 天才能进行一次买卖 所以前 w+1 天只能进行一个操作,那就是买操作。 2. 关于赋初值问题,合法的状态也有可能为负值的,而且结果要取最大值 所以非法状态要赋值为 -INFS. 3. dp[i][j] = max(dp[i-w-1][x] - (j-x)*AP, dp[i-w-1][y] + (y-j)*BP); 另外还有第 i 天什么都不做的情况此时为 dp[i][j] = max(dp[i][j], dp[i-1][j]). 4. 关于转移方程,时间复杂度是很高的,所以要采取单调队列优化 deq[],pos[] 分别放置窗口里面的最大值以及最大值所在的窗口位置。 这里用了一个结构体的队列直接维护这两个信息 5. 如何构造单调队列里面的转移,其实很简单例如 dp[3] = max(dp[1] + 2 * v, dp[2] + 1 * v); 两边同时减去 3 * v 就可以变成一个通项公式了,偏移正好。高中数学知识。 6.推到队列优化也可以这样做,只考虑买的情况,卖的和它对称。 dp[i][j] = max(dp[i-w-1][k]-j*ap[i]+k*ap[i]),移下项变成dp[i][j]+j*ap[i]=max(dp[i-w-1][k]+k*ap[i]), 很明显可以把后面维护成一个递减的单调队列,每次取队首元素,使得复杂度降为O(N*P) */ #include<cstdio> #include<cstring> #define MAX 2005 #define inf 0xfffff #define max(a,b) ((a)>(b)?(a):(b)) using namespace std; int T,MaxP,W; int APi[MAX],BPi[MAX],ASi[MAX],BSi[MAX]; int dp[MAX][MAX];//dp[i][j]第i天持有j股的最大值 //dp[i][j]=max{dp[i-1][j],max{dp[r][k]-APi[i]*(j-k)}(0<r<i-w,k<j),max{dp[r][k]+BPi[i]*(k-j)}(0<r<i-w,k>j)} struct node { int x;//存dp[i-w-1][k]+APi[i]*k或dp[i-w-1][k]+BPi[i]*k int p;//当前持股数 } q[2005],temp; int front,back; int main() { int cas; scanf("%d",&cas); for(; cas--;) { scanf("%d%d%d",&T,&MaxP,&W); for(int i=1; i<=T; ++i) scanf("%d%d%d%d",APi+i,BPi+i,ASi+i,BSi+i); for(int i=0; i<=T; ++i) for(int j=0; j<=MaxP; ++j) dp[i][j]=-inf; for(int i=1; i<=W+1; ++i) for(int j=0; j<=ASi[i]; ++j) dp[i][j]=(-APi[i]*j); for(int i=2; i<=T; ++i) { for(int j=0; j<=MaxP; ++j) dp[i][j]=max(dp[i][j],dp[i-1][j]); if(i<=W+1) continue; //买入 front=back=1; for(int j=0; j<=MaxP; ++j) { temp.p=j; temp.x=dp[i-W-1][j]+APi[i]*j; for(;front<back&&q[back-1].x<temp.x;--back); q[back++]=temp; for(;front<back&&q[front].p+ASi[i]<j;++front); dp[i][j]=max(dp[i][j],q[front].x-APi[i]*j); } //卖出 front=back=1; for(int j=MaxP; j>=0; --j) { temp.p=j; temp.x=dp[i-W-1][j]+BPi[i]*j; for(;front<back&&q[back-1].x<temp.x;--back); q[back++]=temp; for(;front<back&&q[front].p-BSi[i]>j;++front); dp[i][j]=max(dp[i][j],q[front].x-BPi[i]*j); } } int ans=0; for(int i=0;i<=MaxP;++i) ans=max(ans,dp[T][i]); printf("%d\n",ans); } return 0; }