HDU-3401:Trade(dp+单调队列优化)
来源:互联网 发布:李氏筋骨散淘宝 编辑:程序博客网 时间:2024/05/18 02:16
题目链接:点击打开链接
题目大意:
就是有一个人知道每一天的股票的购入和卖出的价钱(注意只有一种股票),并且每天能够购入和卖出的股票的数量也是有限制的。第 i 天买的股票也只能第 i+w+1 天卖出。但是无论何时,他手中持有的股票的数量不能超过m、问他本金无限的情况下最多盈利多少。
题意解析:
很容易分析出来是一道dp题目 每一天的状态可以由他 i-w-1 天前的状态推出来,再枚举他今天 买入 或 卖出 多少股票。dp转移方程就不说了。来说一下这道题需要用到的一个技巧,单调队列优化 dp 。
单调队列优化dp,刚开始着实理解不来 。看大佬代码一头雾水。遂决定先去写个超时代码。果然超时代码写出来之后对比着就比较容易理解了。
单调队列dp 适用于 dp[i]=max/min (f[k]) + g[i] (k<i && g[i]是与k无关的变量)(借用一下大佬的)这种情况。
接下来谈我自己对单调队列的理解,当然不一定正确,自己瞎猜的。因为 k 是与 i 有关的,理论上来说 我们若想得出正确答案,最暴力的方法是枚举完 i 再枚举 k 。这样的话就是一个双重循环。但是单调队列可以帮助我们一重循环解决。就是直接将 i 枚举一遍。枚举 i 的同时也同时将 k 作为 i 枚举。但是因为 k 和 i 之间有某种关系 。所以我们需要将枚举出来的 i 先保存起来,维护一个单调队列。那么对于你枚举到后面的 i 的时候,这个单调队列里面的头结点对应的 i 一定是最优解并且他将作为 k 参加dp转移方程。这样就可以一重循环完美的解决问题了。不得不说真的神奇。
下面贴两段代码,一个超时,一个是优化过的。对比着看的话应该更容易理解。
/* 优化版 */#include <iostream>#include <cstdio>#include <cstring>#include <cstdlib>#include <cmath>#include <vector>#include <queue>#include <map>#include <algorithm>#include <set>#include <functional>#define lson rt<<1#define rson rt<<1|1using namespace std;typedef long long ll;const int INF = 1e9 + 5;int n,m,w,ans;struct node{ int idx; int kk;};int ap[2005],bp[2005];int as[2005],bs[2005];int dp[2005][2005];node q[2005]; //单调队列int main(){ int QAQ; scanf("%d",&QAQ); while(QAQ--) { scanf("%d%d%d",&n,&m,&w); for(int i=1;i<=n;i++) scanf("%d%d%d%d",&ap[i],&bp[i],&as[i],&bs[i]); for(int i=0;i<=n;i++) for(int j=0;j<=m;j++) dp[i][j]=-INF; for(int i=1;i<=w+1;i++) //预处理前w+1天的情况 for(int j=0;j<=min(as[i],m);j++) dp[i][j]=-j*ap[i]; dp[0][0]=0; int head=0,tail=0; for(int i=1;i<=n;i++) { for(int j=0;j<=m;j++) dp[i][j]=max(dp[i][j],dp[i-1][j]); //不买不卖的情况 if(i<=w+1) continue ; int g=i-w-1,gg; head=0;tail=0; for(int j=0;j<=m;j++) //买入情况 枚举 j { gg=dp[g][j]+j*ap[i]; while(head<tail&&q[tail-1].kk<gg) // 将j不断加入单调队列并维护 tail--; q[tail].idx=j;q[tail++].kk=gg; while(head<tail&&q[head].idx+as[i]<j) //将前面部分不符合要求的点去掉 head++; dp[i][j]=max(dp[i][j],q[head].kk-j*ap[i]); //当前最优状态转移方程 } head=0;tail=0; for(int j=m;j>=0;j--) //卖出 同上 { gg=dp[g][j]+j*bp[i]; while(head<tail&&q[tail-1].kk<gg) tail--; q[tail].idx=j;q[tail++].kk=gg; while(head<tail&&q[head].idx-bs[i]>j) head++; dp[i][j]=max(dp[i][j],q[head].kk-j*bp[i]); } } ans=0; for(int i=0;i<=m;i++) ans=max(ans,dp[n][i]); printf("%d\n",ans); }}
/* 未优化版 */#include <iostream>#include <cstdio>#include <cstring>#include <cstdlib>#include <cmath>#include <vector>#include <queue>#include <map>#include <algorithm>#include <set>#include <functional>#define lson rt<<1#define rson rt<<1|1using namespace std;typedef long long ll;const int INF = 1e9 + 5;int n,m,w,ans;int ap[2005],bp[2005];int as[2005],bs[2005];int dp[2005][2005];int q[2005];int main(){ int QAQ; scanf("%d",&QAQ); while(QAQ--) { scanf("%d%d%d",&n,&m,&w); for(int i=1;i<=n;i++) scanf("%d%d%d%d",&ap[i],&bp[i],&as[i],&bs[i]); for(int i=0;i<=n;i++) for(int j=0;j<=m;j++) dp[i][j]=-INF; for(int i=1;i<=w+1;i++) { for(int j=0;j<=min(as[i],m);j++) dp[i][j]=-j*ap[i]; } dp[0][0]=0; for(int i=1;i<=n;i++) { for(int j=0;j<=m;j++) dp[i][j]=max(dp[i][j],dp[i-1][j]); if(i<=w+1) continue ; int g=i-w-1; for(int j=m;j>=0;j--) for(int k=0;k+as[i]<j;k++) //重点看k的范围 单调队列要用到 dp[i][j]=max(dp[g][k]-(j-k)*ap[i],dp[i][j]); for(int j=0;j<=m;j++) for(int k=min(j+bs[i],m);k>j;k--) //同上 dp[i][j]=max(dp[g][k]+(k-j)*bp[i],dp[i][j]); } ans=0; for(int i=0;i<=m;i++) ans=max(ans,dp[n][i]); printf("%d\n",ans); }}
- 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+单调队列
- Java----DVD管理系统
- 认识工作流框架
- Create-React-App创建antd-mobile开发环境
- spring cloud
- 测试基础知识
- HDU-3401:Trade(dp+单调队列优化)
- 很厉害的一个数据库连接工具类
- struts2页面下载,从数据库把数据以excel表格形式导出
- POSIX多线程程序设计学习篇之一(线程管理)
- Vitamio 的导入过程
- Hibernate和Mybatis对比(优缺点)
- linux 下卸载PHP
- C语言之指针篇
- 【正一专栏】共享单车那些事儿