HDU 3401 Trade(用单调队列优化DP)
来源:互联网 发布:php开源电子商务系统 编辑:程序博客网 时间:2024/05/22 14:49
题目链接:点击打开链接
题意:给出T天内,每天的股票买卖价格和每天的股票买卖最大数量,而且最多只能拥有maxP数量的股票,开始时有无限本金,任意两次交易需要间隔W天及以上,也就是第i天交易,第i+w+1天及以后才能再交易。问最多能赚多少钱?(题意应该还有一个隐晦的要求是,当天只能买股票或者卖股票,不能同时做)
思路:很明显的DP问题,用dp[i][j]表示第i天拥有j数量股票时的最多赚钱数。容易得到状态转移方程:
(1)当天不买不卖:
dp[i][j] = max(dp[i][j],dp[i - 1][j])
(2)买股票:
dp[i][j] = max(dp[i][j],dp[h][k] - (j - k)* APi[i]),1 <= h <= i - W - 1,0 <= k <= j
(3)卖股票:
dp[i][j] = max(dp[i][j],dp[h][k] +(k - j)* BPi[i]),1 <= h <= i - W - 1,j < k <= maxP
可以看出,这个状态转移方程变量太多,不便于处理,因此必须进行优化:
优化一:h必需的吗?否
由状态转移方程(1),第i - W - 1天可以看作前一天不买不卖得到的,依次类推,可以看出,之前的都不需要考虑了,只考虑第i - W - 1天的情况即可。
则:
买股票:
dp[i][j] = max(dp[i][j],dp[i - W -1][k] - (j - k)* APi[i]),0 <= k <= j
卖股票:
dp[i][j] = max(dp[i][j],dp[i - W -1][k] +(k - j)* BPi[i]),j < k <= maxP
优化二:优化一后,现在仍需要枚举i、j、k三个量,O(n ^ 3)的复杂度,容易超时。以(2)为例,dp[i][j] = max(dp[i][j],dp[i - W - 1][k] - (j - k)* APi[i])= max(dp[i][j],dp[i - W -1][k] + k * APi[i] - j * APi[i]),符合单调队列优化DP的基本形式:dp[i] = max / min (f[k])+ g[i] (k < i && g[i]是与k无关的变量),这样通过单调队列对dp方程进行优化,将O(n)复杂度降至O(1)(均摊),减少k这层枚举,使复杂度达到O(n ^ 2)。
// HDU 3401 Trade 运行/限制:218ms/1000ms#include <cstdio>#include <cstring>#include <algorithm>#include <iostream>using namespace std;#define INF 0X3f3f3f3fint T, maxP, W;//总天数 可拥有股票最多数量int APi[2005],BPi[2005],ASi[2005],BSi[2005];//当天买股票的价格 当天卖股票的价格 当天最多买的股票 当天最多卖的股票int dp[2005][2005];struct node {int num;//股票数量int m;//dp[i - W - 1][k] + k * Api[i]或者 dp[i - W - 1][k] + k * BPi[i]};node queue[2005];int head, tail;int main(){int t;scanf("%d", &t);while (t--) {scanf("%d%d%d", &T, &maxP, &W);for (int i = 1; i <= T; i++) {scanf("%d%d%d%d", &APi[i], &BPi[i], &ASi[i], &BSi[i]);}//初始化dp数组for (int i = 0; i <= T; i++) {for (int j = 0; j <= maxP; j++) {dp[i][j] = -INF;}}//预处理前W+1天for (int i = 1; i <= W + 1; i++) {for (int j = 0; j <= min(maxP,ASi[i]); j++) {//买股票dp[i][j] = -j*APi[i];}}dp[0][0] = 0;for (int i = 1; i <= T; i++) {//天数for (int j = 0; j <= maxP; j++) {//第i天不买不卖dp[i][j] = max(dp[i][j], dp[i - 1][j]);}if (i - W - 1 <= 0) continue;int pre = i - W - 1;//买股票head = 1;tail = 0;for (int j = 0; j <= maxP; j++) {//股票数量int f = dp[pre][j] + APi[i] * j;while (head <= tail && queue[tail].m <= f) {tail--;}queue[++tail].num = j;queue[tail].m = f;while (head <= tail && queue[head].num + ASi[i] < j) {head++;}dp[i][j] = max(dp[i][j], queue[head].m - APi[i] * j);}//卖股票head = 1;tail = 0;for (int j = maxP; j >= 0; j--) {//股票数量int f = dp[pre][j] + BPi[i] * j;while (head <= tail && queue[tail].m <= f) {tail--;}queue[++tail].num = j;queue[tail].m = f;while (head <= tail && queue[head].num - BSi[i] > j) {head++;}dp[i][j] = max(dp[i][j], queue[head].m - BPi[i] * j);}}int re = -INF;for (int i = 0; i <= maxP; i++) {re = max(re, dp[T][i]);}printf("%d\n", re);} return 0;}
- HDU 3401 Trade(用单调队列优化DP)
- hdu 3401 Trade(DP+单调队列优化)
- hdu 3401 Trade 单调队列优化dp
- hdu 3401 Trade 单调队列优化dp
- hdu 3401 Trade(单调队列优化dp)
- HDU 3401 Trade 单调队列优化DP
- HDU 3401 Trade 【DP+单调队列优化】
- HDU 3401 Trade (单调队列优化DP)
- HDU-3401:Trade(dp+单调队列优化)
- HDU 3401 Trade(单调队列优化DP)【模板】
- hdu 3401 Trade (单调队列优化)
- hdu-3401-Trade-单调队列优化的DP
- hdu3401 Trade(单调队列优化dp)
- Trade HDU 3401 单调队列DP
- hdu 3401 Trade //单调队列+DP
- HDU 3401 Trade【单调队列+dp】
- hdu 3401 Trade 单调队列+dp
- hdu 3401 Trade dp+单调队列
- Jzoj1164求和
- CCF—消除类游戏 20151202
- Java中的static关键字解析
- sizeof 知多少?
- 商品库存信息管理
- HDU 3401 Trade(用单调队列优化DP)
- LeetCode-全排列
- 51nod 1005大数相加
- 实验一线性表的基本操作实现及其应用
- A Cubic number and A Cubic Number
- 2017多校训练赛第四场 HDU 6078 Wavel Sequence(dp+优化)
- 算法竞赛入门经典(第2版)笔记--第3章
- jdbc创建后创建bean
- linux中编译安装Apache、PHP、MySQL(上)