[单调队列DP] HDU3401 Trade
来源:互联网 发布:北京建筑大学网络 编辑:程序博客网 时间:2024/05/17 09:14
Trade
题意:
炒股,给出第1~t天每天的买入价格Ap[i]和卖出价格Bp[i],每天最多能买入的数量As[i]和最多能卖出的数量Bs[i]。
还有几个限制,任意时刻最多持有Pmax数量的股票,两次交易(买入或卖出)间隔至少w天,如第i天交易,那么下次至少是i+w+1天。问你第t天最大收入。
题解:
首先考虑朴素DP。
令
讨论转移方程:
第i天啥也不干:
第i天买点,显然有
第i天卖点,显然有
然后每天能干的事就考虑完了,接下来考虑代码实现。
for(int i = 1; i <= t; ++i){ for(int j = 0; j <= p; ++j){ int mx = -inf; mx = max(dp[i][j], dp[i-1][j]); if(i <= w+1) continue; for(int k = j; k >= 0 && j-k <= As[i]; --k){ mx = max(mx, dp[i-w-1][k]-(j-k)*Ap[i]); } for(int k = j; k <= p && k-j <= Bs[i]; ++k){ mx = max(mx, dp[i-w-1][k]+(k-j)*Bp[i]); } dp[i][j] = mx; }}
我写出来是这样的,这是个
那就要想优化了。
第一个方程是
看第二个方程。
整理一下。
再令
那么方程可以这样转化:
那么转移完的结果就是
单调队列就是针对这样的方程进行优化的。
一般的,对于类似
代码实现上,根据维护的信息范围不同,遍历的顺序就不同。
#include<stdio.h>#include<algorithm>#include<string.h>using namespace std;const int inf = ~0u>>2;const int N = 2005;int dp[N][N]; // 第i天拥有j股票情况下的最大收入// dp[i][j] = dp[i-1][j];// dp[i][j] = dp[i-w-1][k]+k*Api-j*Api; j <= p && j-k <= Asi 买入// dp[i][j] = dp[i-w-1][k]+k*Bpi-j*Bpi; j >= 0 k-j <= Bsi 卖出//// 令 f[i-w-1][k] = dp[i-w-1][k]+k*Api// dp[i][j] = max(f[i-w-1][k]) - j*Api; j > k//// 令f[i-w-1][k] = dp[i-w-1][k]+k*Bpi// dp[i][j] = max(f[i-w-1][k]) - j*Bpi j < kint As[N], Bs[N], Ap[N], Bp[N];int top, tail;struct node{ int val, pos; node(){} node(int a, int b){ val = a, pos = b;}}q[N*10];int main(){ int T; scanf("%d", &T); while(T--){ int t, p, w; scanf("%d%d%d", &t, &p, &w); for(int i = 1; i <= t; ++i) scanf("%d%d%d%d", Ap+i, Bp+i, As+i, Bs+i); for(int i = 0; i <= t; ++i) for(int j = 0; j <= p; ++j) dp[i][j] = -inf; for(int i = 1; i <= w+1; ++i){ int up = min(p, As[i]); for(int j = 0; j <= up; ++j){ dp[i][j] = -j*Ap[i]; } } for(int i = 1; i <= t; ++i){ top = tail = 0; for(int j = 0; j <= p; ++j){ dp[i][j] = max(dp[i][j], dp[i-1][j]); if(i <= w+1) continue; int nf = dp[i-w-1][j]+j*Ap[i]; while(top < tail && q[tail-1].val < nf) tail--; q[tail++] = node(nf, j); while(top < tail && j-q[top].pos > As[i]) top++; dp[i][j] = max(dp[i][j], q[top].val-j*Ap[i]); } top = tail = 0; for(int j = p; j >= 0; --j){ dp[i][j] = max(dp[i][j], dp[i-1][j]); if(i <= w+1) break; int nf = dp[i-w-1][j]+j*Bp[i]; while(top < tail && q[tail-1].val < nf) tail--; q[tail++] = node(nf, j); while(top < tail && q[top].pos-j > Bs[i]) top++; dp[i][j] = max(dp[i][j], q[top].val-j*Bp[i]); } } int ans = 0; for(int i = 0; i <= p; ++i) ans = max(ans, dp[t][i]); printf("%d\n", ans); }}
- 【DP+单调队列】 hdu3401 Trade
- [单调队列DP] HDU3401 Trade
- Trade-----HDU3401----单调队列优化的DP
- hdu3401 Trade 单调队列优化dp
- [HDU3401]Trade && 单调队列优化DP
- hdu3401 Trade 单调队列优化DP
- hdu3401 Trade [单调队列优化dp]
- hdu3401 Trade(单调队列优化dp)
- 【HDU3401】Trade-单调队列优化DP
- [hdu3401] Trade DP单调队列优化
- 单调队列 hdu3401 Trade
- 单调队列 例子:hdu3401 trade(dp加单调队列)
- Hdu3401 Trade(dp 单调队列优化)最详细题解
- HDU3401 Trade (动态规划+单调队列)
- HDU3401 单调队列优化DP
- 单调队列优化dp [HDU2191][HDU3401][POJ1821]
- HDU3401(dp + 单调队列优化)
- Trade HDU 3401 单调队列DP
- c++中的日期和时间
- 面试题之替换空格
- C#读取Excel数据到数组
- 大牛们的博客
- 回溯水题——置棋问题
- [单调队列DP] HDU3401 Trade
- C#中的代码书写规范以及命名规范
- Bellman-Ford算法模板
- Android For JNI(一)——JNI的概念以及C语言开发工具dev-c++,编写你的第一个C语言程序,使用C启动JAVA程序
- 南阳题目364-田忌赛马
- 素数环
- CF 236A boy or girl
- 对HashMap中的值进行排序
- 【SDOI2014】数数