题目链接: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\n",ans);
54 }
55 }
来源:https://www.cnblogs.com/qzqzgfy/p/5553712.html