hdu 3401 单调队列优化+dp

http://acm.hdu.edu.cn/showproblem.php?pid=3401

Trade

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 5188    Accepted Submission(s): 1776

Problem Description

Recently, lxhgww is addicted to stock, he finds some regular patterns after a few days‘ study.
He
forecasts the next T days‘ stock market. On the i‘th day, you can buy
one stock with the price APi or sell one stock to get BPi.
There are some other limits, one can buy at most ASi stocks on the i‘th day and at most sell BSi stocks.
Two
trading days should have a interval of more than W days. That is to
say, suppose you traded (any buy or sell stocks is regarded as a
trade)on the i‘th day, the next trading day must be on the (i+W+1)th day
or later.
What‘s more, one can own no more than MaxP stocks at any time.

Before
the first day, lxhgww already has infinitely money but no stocks, of
course he wants to earn as much money as possible from the stock market.
So the question comes, how much at most can he earn?

Input

The first line is an integer t, the case number.
The first line of each case are three integers T , MaxP , W .
(0 <= W < T <= 2000, 1 <= MaxP <= 2000) .
The
next T lines each has four integers APi,BPi,ASi,BSi(
1<=BPi<=APi<=1000,1<=ASi,BSi<=MaxP), which are mentioned
above.

Output

The most money lxhgww can earn.

Sample Input

1
5 2 0
2 1 1 1
2 1 1 1
3 2 1 1
4 3 1 1
5 4 1 1

Sample Output

3

感觉初始化有点坑,,,,

由于间隔w天才能进行第二次购买,对于第i天想进行交易的股票来说之前的w天如果可以转移说明之前没进行过交易,所以这几天的数值都一样,所以不必重复的更新,

只从前i-w-1这一天转移就好了。

so  f[i][j]=MAX{f[i][j-1], f[i-w-1][k]-(j-k)*ap[i] k<=j&&j-k<=as[i], f[i-w-1][k]+(k-j)*bp[i] | k>=j&&k-j<=bs[i] };

显然可以用单调队列加速,但是注意要提前处理前w天所有购买后的花费, 因为对于i-w-1小于零的天我们直接忽略,导致并没有计算他们,所以切记初始化!

不必考虑前w+1天卖,因为如果想卖说明前面买了,但是两天都处于前w+1天中间隔肯定小于w天,因此证明得前w+1天里不可能发生卖的操作!

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<queue>
 5 #include<algorithm>
 6 using namespace std;
 7 #define inf 120
 8 #define LL long long
 9 inline int read(int f = 1)
10 {
11     char c = getchar();while (!isdigit(c)) { if (c == ‘-‘)f = -1; c = getchar(); }
12     int r = 0; while (isdigit(c)) { r = r * 10 + c - ‘0‘;c = getchar(); } return r*f;
13 }
14 int f[2005][2005];
15 int ap[2005], bp[2005], as[2005], bs[2005];
16 struct node2 { int w, k; };
17 deque<node2>q;
18 int main()
19 {
20     int i, j, k, cas, T, MAX_P, W;
21     cin >> cas;
22     while (cas--) {
23         T = read();
24         MAX_P = read();
25         W = read();
26         for (i = 1;i <= T;++i)
27         {
28             ap[i] = read();
29             bp[i] = read();
30             as[i] = read();
31             bs[i] = read();
32         }
33         memset(f, -inf, sizeof(f));
34         for (int i = 1; i <= W + 1; i++) {//第一天到W+1天只都是只能买的
35             for (int j = 0; j <= min(MAX_P, as[i]); j++) {
36                 f[i][j] = -ap[i] * j;
37             }
38         }
39         f[0][0] = 0;
40         for (i = 1;i <= T;++i)
41         {
42             int u = i - W - 1;
43             for (j = 0;j <= MAX_P;++j)
44             {
45                 f[i][j] = max(f[i][j],f[i - 1][j]);
46                 if (u < 0)continue;
47                 while (!q.empty() && q.back().w < f[u][j] + j*ap[i])q.pop_back();
48                 q.push_back(node2{f[u][j]+j*ap[i],j});
49                 while (!q.empty() && j - q.front().k > as[i])q.pop_front();
50                 if (!q.empty()) f[i][j] = max(f[i][j], q.front().w - j*ap[i]);
51             }
52             if (u < 0)continue;
53             q.clear();
54             for (j = MAX_P;j >= 0;--j)
55             {
56                 while (!q.empty() && q.back().w < f[u][j] + j*bp[i])q.pop_back();
57                 q.push_back(node2{f[u][j]+j*bp[i],j});
58                 while (!q.empty() &&  q.front().k -j> bs[i])q.pop_front();
59                 if (!q.empty()) f[i][j] = max(f[i][j], q.front().w - j*bp[i]);
60             }
61             q.clear();
62         }
63         int ans = 0;
64         for (i = 0;i <= MAX_P;++i)
65             ans = max(ans,f[T][i]);
66         printf("%d\n", ans);
67     }
68     return 0;
69 }
时间: 2024-12-29 07:51:05

hdu 3401 单调队列优化+dp的相关文章

hdu 3401(单调队列优化dp)

注意:这题题意是有操作的天数相隔要大于w 然后列出状态转移方程就可以发现,可以用优点队列优化啦. 构造状态dp[i][j]表示第i 天拥有 j只股票的时候,赚了多少钱 状态转移有: 1.从前一天不买不卖: dp[i][j]=max(dp[i-1][j],dp[i][j]) 2.从前i-W-1天买进一些股: dp[i][j]=max(dp[i-W-1][k]-(j-k)*AP[i],dp[i][j]) 3.从i-W-1天卖掉一些股: dp[i][j]=max(dp[i-W-1][k]+(k-j)*

HDU 4122 Alice&#39;s mooncake shop 单调队列优化dp

Alice's mooncake shop Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=4122 Description The Mid-Autumn Festival, also known as the Moon Festival or Zhongqiu Festival is a popular harvest festival celebrated by Ch

Parade(单调队列优化dp)

题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=2490 Parade Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 902    Accepted Submission(s): 396 Problem Description Panagola, The Lord of city F lik

Tyvj1305最大子序和(单调队列优化dp)

描述 输入一个长度为n的整数序列,从中找出一段不超过M的连续子序列,使得整个序列的和最大. 例如 1,-3,5,1,-2,3 当m=4时,S=5+1-2+3=7当m=2或m=3时,S=5+1=6 输入格式 第一行两个数n,m第二行有n个数,要求在n个数找到最大子序和 输出格式 一个数,数出他们的最大子序和 测试样例1 输入 6 4 1 -3 5 1 -2 3 输出 7 备注 数据范围:100%满足n,m<=300000 是不超过m,不是选m个!!!!! /* 单调队列优化dp 单调队列维护的是前

bzoj1855: [Scoi2010]股票交易--单调队列优化DP

单调队列优化DP的模板题 不难列出DP方程: 对于买入的情况 由于dp[i][j]=max{dp[i-w-1][k]+k*Ap[i]-j*Ap[i]} AP[i]*j是固定的,在队列中维护dp[i-w-1][k]+k*Ap[i]的单调性即可 1 #include<stdio.h> 2 #include<string.h> 3 #include<algorithm> 4 using namespace std; 5 const int maxn = 2010; 6 int

1855: [Scoi2010]股票交易[单调队列优化DP]

1855: [Scoi2010]股票交易 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 1083  Solved: 519[Submit][Status][Discuss] Description 最近lxhgww又迷上了投资股票,通过一段时间的观察和学习,他总结出了股票行情的一些规律. 通过一段时间的观察,lxhgww预测到了未来T天内某只股票的走势,第i天的股票买入价为每股APi,第i天的股票卖出价为每股BPi(数据保证对于每个i,都有APi>=

BZOJ 1855 股票交易(单调队列优化DP)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1855 题意:最近lxhgww又迷上了投资股票, 通过一段时间的观察和学习,他总结出了股票行情的一些规律. 通过一段时间的观察,lxhgww预测到了未来T天内某只股票的走势,第i天的股票买入价为每股APi,第i天的股票卖出价为每股BPi(数据保证对于每 个i,都有APi>=BPi),但是每天不能无限制地交易,于是股票交易所规定第i天的一次买入至多只能购买ASi股,一次卖出至多只能卖出BS

【单调队列优化dp】uestc 594 我要长高

http://acm.uestc.edu.cn/#/problem/show/594 [AC] 1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn=5e4+2; 5 const int inf=0x3f3f3f3f; 6 int n,c; 7 int cur; 8 int dp[2][maxn]; 9 int q[maxn]; 10 int main() 11 { 1

洛谷P1725 琪露诺 单调队列优化 DP

洛谷P1725 琪露诺 单调队列优化 DP 题意:1--n 每个点都有一个权值,从当前点i可以到达i+l--i+r 之间的点, 动态规划 方程 为 f[ i ] = max(f[ i ],f[ k ] ) +a[ i ] i-r<=k<=i-l 然而这样复杂度 就为 n^2 因为相当于 dp 是在求 一段区间的最大值,而这个最大值就可以用O(n) 来维护 注意 这个O(n) 是均摊O(n) 即将所有固定区间长度的 最大值求出来 是 O(n)的这样就把复杂度降到 O(n) 级别了 1 #incl