HDU 3401 Trade dp 单调队列优化

戳这里:3401

题意:给出第 i 天的股票买卖价格(APi,BPi),以及每天股票买卖的数量上限(ASi,BSi),要求任两次交易需要间隔 W 天以上,即第 i 天交易,第 i + W + 1 天才能再交易,求最多能赚多少钱

思路:dp[i][j] = max(dp[i - 1][j], max(dp[f][k] - (j - k) * APi[i]), max(dp[f][k] + (k - j) * BPi[i])); 从式子中观察出,若两天都持有股票数 j 时,之后的那一天所赚的钱不小于之前的那一天,所以可以省去对 f 的枚举,即:

dp[i][j] = max(dp[i - 1][j], max(dp[i - 1 - w][k] - (j - k) * APi[i]), max(dp[i - 1 - w][k] + (k - j) * BPi[i]));

观察到,决策2 j > k,决策3 k > j,且两天所持股票数相近的话,发生状态转移的可能性越大,故可以对 k 进行单调队列优化,

决策2 化为 max(dp[i - 1 - w][k] + k * APi[i]) - j * APi[i]; (j >= k)

决策3 化为 max(dp[i - 1 - w][k] + k * BPi[i]) - j * BPi[i]; (j <= k)

 1 #include "bits/stdc++.h"
 2 using namespace std;
 3 int t;
 4 int T, MaxP, W;
 5 int APi[2010], BPi[2010], ASi[2010], BSi[2010];
 6 
 7 int dp[2010][2010];
 8 struct Queue
 9 {
10     int value, index;
11 }q[2010], tmp;
12 int front, rear;
13 
14 //dp[i][j] = max(dp[i - 1][j], max(dp[i - 1 - w][k] - (j - k) * APi[i]), max(dp[i - 1 - w][k] + (k - j) * BPi[i]));
15 //决策2 化为 max(dp[i - 1 - w][k] + k * APi[i]) - j * APi[i]; (j >= k)
16 //决策3 化为 max(dp[i - 1 - w][k] + k * BPi[i]) - j * BPi[i]; (j <= k)
17 
18 int main()
19 {
20     scanf("%d", &t);
21     while(t--) {
22         //初始化
23         memset(dp, 0xf3, sizeof(dp));
24         //输入
25         int i, j, k;
26         scanf("%d%d%d", &T, &MaxP, &W);
27         for(i = 1; i <= T; ++i) {
28             scanf("%d%d%d%d", &APi[i], &BPi[i], &ASi[i], &BSi[i]);
29         }
30         //处理前驱不完全的状态
31         for(i = 1; i <= W + 1; ++i) {
32             for(j = 0; j <= ASi[i]; ++j) {  //之前这里写成 j <= MaxP WA了一次
33                 dp[i][j] = -j * APi[i];
34             }
35         }
36         //从首个后继状态开始 dp
37         for(i = 2; i <= T; ++i) {
38             //决策1
39             for(j = 0; j <= MaxP; ++j) {
40                 dp[i][j] = max(dp[i][j], dp[i - 1][j]);
41             }
42             if(i <= W + 1) {
43                 continue;
44             }
45             //决策2
46             front = rear = 1;
47             for(j = 0; j <= MaxP; ++j) {
48                 tmp.index = j;
49                 tmp.value = dp[i - 1 - W][j] + j * APi[i];
50                 for( ; front < rear && tmp.value > q[rear - 1].value; --rear);
51                 q[rear++] = tmp;
52                 for( ; front < rear && q[front].index + ASi[i] < j; ++front);
53                 dp[i][j] = max(dp[i][j], q[front].value - j * APi[i]);
54             }
55             //决策3
56             front = rear = 1;
57             for(j = MaxP; j >= 0; j--) {
58                 tmp.index = j;
59                 tmp.value = dp[i - 1 - W][j] + j * BPi[i];
60                 for( ; front < rear && tmp.value > q[rear - 1].value; --rear);
61                 q[rear++] = tmp;
62                 for( ; front < rear && q[front].index - BSi[i] > j; ++front);
63                 dp[i][j] = max(dp[i][j], q[front].value - j * BPi[i]);
64             }
65         }
66         int res = 0;
67         for(j = 0; j <= MaxP; ++j) {
68             res = max(res, dp[T][j]);
69         }
70         printf("%d\n", res);
71     }
72 }

 

posted @ 2015-05-08 11:28  AC_Phoenix  阅读(183)  评论(0编辑  收藏  举报