HDU 3401 Trade(单调队列优化)

一曲冷凌霜 提交于 2019-12-18 11:53:27

题目链接: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 }

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!