题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3401
题意:炒股。第i天买入一股的价钱api,卖出一股的价钱bpi,最多买入asi股,最多卖出bsi股。两次操作(买入或卖出)中间必须相差W天。炒股时间为n。任意时间手中的股票不大于MaxP。求最大收益。
dp[i][j]代表第i天手上有j股的最大收益,dp[i][j]=max(dp[i-1][j],dp[i-W][k]+(j-k)*ap[i],dp[i-W][k]+(k-j)*bp[i]);
dp[i-W][k]+j*ap[i]-k*ap[i];
dp[i-W][k]+k*bp[i]-j*bp[i];
用单调队列维护
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 #include<string> 6 #include<algorithm> 7 #define inf 0x7fffffff 8 struct op{ 9 int x,p; 10 }q[20005],temp; 11 int n,m,w; 12 int ap[2005],bp[2005],as[2005],bs[2005]; 13 int dp[2005][2005],h,t; 14 int main(){ 15 int Tcase; 16 scanf("%d",&Tcase); 17 while (Tcase--){ 18 scanf("%d%d%d",&n,&m,&w); 19 for (int i=1;i<=n;i++) 20 scanf("%d%d%d%d",&ap[i],&bp[i],&as[i],&bs[i]); 21 for (int i=1;i<=n;i++) 22 for (int j=0;j<=m;j++) 23 dp[i][j]=-inf; 24 for (int i=1;i<=w+1;i++) 25 for (int j=0;j<=as[i];j++) 26 dp[i][j]=-ap[i]*j; 27 for (int i=2;i<=n;i++){ 28 for (int j=0;j<=m;j++) 29 dp[i][j]=std::max(dp[i][j],dp[i-1][j]); 30 if (i<=w+1) continue; 31 h=t=1; 32 for (int j=0;j<=m;j++){ 33 temp.p=j; 34 temp.x=dp[i-w-1][j]+ap[i]*j; 35 for (;h<t&&q[t-1].x<temp.x;t--); 36 q[t++]=temp; 37 for (;h<t&&q[h].p+as[i]<j;h++); 38 dp[i][j]=std::max(dp[i][j],q[h].x-ap[i]*j); 39 } 40 h=t=1; 41 for (int j=m;j>=0;j--){ 42 temp.p=j; 43 temp.x=dp[i-w-1][j]+bp[i]*j; 44 for (;h<t&&q[t-1].x<temp.x;t--); 45 q[t++]=temp; 46 for (;h<t&&q[h].p-bs[i]>j;h++); 47 dp[i][j]=std::max(dp[i][j],q[h].x-bp[i]*j); 48 } 49 } 50 int ans=0; 51 for (int i=0;i<=m;i++) 52 ans=std::max(ans,dp[n][i]); 53 printf("%d ",ans); 54 } 55 }