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 }

你可能感兴趣的:(HDU)