HDU 3401

最近遇到不少DP优化的题,感觉这方面还有些欠缺,现在就多做点这方面的题,练练手。

这题是道较为经典的单调队列优化的题,总共有三种状态,买,卖及其他。

对于买:dp[i][j] = max(dp[i][j],dp[x][y] - (j-y)*sell) (y<=j && y+买的限制>=j &&  0 <= x <= i-w-1)

对于卖:dp[i][j] = max(dp[i][j],dp[x][y] + (y-j)*buy) (y >= j && j + 卖的限制 >= y && 0 <= x <= i-w-1)。

优化主要在T,和MAXP上。

View Code
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cmath>
 5 #include<deque>
 6 #define MAXN 2012
 7 #define INF -(1<<29)
 8 using namespace std;
 9 int dp[MAXN][MAXN];
10 int b_price[MAXN];
11 int s_price[MAXN];
12 int b_stock[MAXN];
13 int s_stock[MAXN];
14 
15 void get_dp(int n, int w, int p)
16 {
17     int ans = INF;
18     dp[0][0] = 0;
19     int b[MAXN];
20     int s[MAXN];
21     for (int i(0); i<n; ++i) {
22         int b_h(-1),b_e(-1),s_h(-1),s_e(-1);
23         for (int j(0),k(0); j<=p; ++j) {
24             if (i <= w && j <= b_stock[i])dp[i][j] = max(dp[i][j],-b_price[i]*j);
25             if (i != 0)dp[i][j] = max(dp[i][j],dp[i-1][j]);
26             if (i > w) {
27                 while (b_h != b_e && b[b_h+1] + b_stock[i] < j) ++b_h;
28                 while (s_h != s_e && s[s_h+1] < j) ++s_h;
29                 
30                 while (b_h != b_e && dp[i-w-1][b[b_e]] - b_price[i]*(j-b[b_e]) < dp[i-w-1][j])--b_e;
31                 b[++b_e] = j;
32                 dp[i][j] = max(dp[i][j],dp[i-w-1][b[b_h+1]]-b_price[i]*(j-b[b_h+1]));
33                 while (j + s_stock[i] >= k && k <= p) {
34                     while (s_h != s_e && dp[i-w-1][s[s_e]] + s_price[i]*(s[s_e]-j) < dp[i-w-1][k] + s_price[i]*(k-j))--s_e;
35                     s[++s_e] = k;
36                     ++k;
37                 }
38                 dp[i][j] = max(dp[i][j],dp[i-w-1][s[s_h+1]]+s_price[i]*(s[s_h+1]-j));
39             }
40             ans = max(ans,dp[i][j]);
41         }
42     }
43     cout<<ans<<endl;
44 }
45 
46 int main()
47 {
48     int t;
49     scanf("%d",&t);
50     while (t--) {
51         for (int i(0); i<MAXN; ++i) {
52             for (int j(0); j<MAXN; ++j) {
53                 dp[i][j] = INF;
54             }
55         }
56         int n,w,p;
57         scanf("%d%d%d",&n,&p,&w);
58         for (int i(0); i<n; ++i) {
59             scanf("%d%d%d%d",&b_price[i],&s_price[i],&b_stock[i],&s_stock[i]);
60         }
61         get_dp(n,w,p);
62     }
63     return 0;
64 }
posted on 2012-08-27 16:35  Dev-T  阅读(393)  评论(0编辑  收藏  举报