hdu 3401 动态规划 单调DP
题意:给定每天的股票买进上限,买进价格,卖出上限,卖出价格,每两次买卖操作中间必须间隔w天,每天最多持有maxp个股票,问n天后最大收益是多少
分析:dp[i][j]表示第i天有j个股票的最大收益
令 pre = i-w-1
dp[i][j]=max dp[i-1][j] //不买不卖
dp[pre][k] - (j-k)*buy[i] //买j-k个
dp[pre][k] + (k-j)*sell[i] //卖k-j个
即 dp[i][j] + j*buy[i] = max ( dp[pre][k] + k*buy[i] ) ( j-k <= buyn )
dp[i][j] + j*sell[i]= max ( dp[pre][k] + k*sell[i]) ( k-j <= selln )
const int inf=0x80808080; const int MaxN=2002; struct que{ int pos[MaxN], val[MaxN], len, l, r; void init(int le){ l=1; r=0; len=le;} void ins(int p,int v){ while( l<=r && v>=val[r] ) r--;//v<=val[r]即为最小队列 r++; pos[r]=p; val[r]=v; } void dele1(){ while( pos[l]+len < pos[r] ) l++; } void dele2(){ while( pos[r]+len < pos[l] ) l++; } int top() { return val[l]; } }q1,q2; int dp[MaxN][MaxN]; int main(){ memset(dp[0],inf,sizeof(dp[0])); dp[0][0]=0; int T, t, maxp, w; int buy, sell, buyn, selln; scanf("%d",&T); while(T--){ scanf("%d%d%d",&t,&maxp,&w); int ans=inf; FOE(i, 1, t){ scanf("%d%d%d%d",&buy, &sell, &buyn, &selln); if(i <= 1+w){ FOE(j, 0, maxp){ dp[i][j] = dp[i-1][j]; if(j <= buyn && dp[i][j] < -j*buy) dp[i][j] = -j*buy; //if(ans<dp[i][j]) ans=dp[i][j]; } continue; } int pre=i-w-1; q1.init(buyn);//买 FOE(j, 0, maxp){ dp[i][j]=dp[i-1][j]; q1.ins(j,dp[pre][j]+j*buy); q1.dele1(); dp[i][j]=max(dp[i][j],q1.top()-j*buy); } q2.init(selln);//卖 FOD(j, maxp, 0){ q2.ins(j,dp[pre][j]+j*sell); q2.dele2(); dp[i][j]=max(dp[i][j],q2.top()-j*sell); } } for(int j=0;j<=maxp;j++) if(ans<dp[t][j]) ans=dp[t][j]; printf("%d\n",ans); } return 0; }