股票交易



$ solution: $

这道题以前就写了,题目很好,但自己没有发题解,来补一篇:

首先,题目出得很有迷惑性,但我们不难想到状态要设天数,和自己手上的股票数目(因为这两个就是充要信息)。而我们转移也比较常规,跟着题意模拟就行:

  1. (不买不卖): $ f[i][j]=f[i-1][j] $
  2. (买入): $ f[i][j]=max{~\sum_{p=1}^{p<i} \sum_{q=0}^{q<j} f[p][q]-(j-q)\times AP[i]~} $
  3. (卖出): $ f[i][j]=max{~\sum_{p=1}^{p<i} \sum_{q=0}^{q>j} f[p][q]+(q-j)\times BP[i]~} $

但是我们发现这样转移是 $ n^4 $ 的。因为我们每一个 $ f[i][j] $ 需要往前枚举 $ p $ ,然后因为股票可以买入卖出,还要枚举一个 $ q $ 。就是每一个 $ f[i][j] $ 都要完全枚举所有的 $ f[p][q] $ 来转移。但是我们可以发现我们的 $ p $ 是完全可以不用枚举,因为第一个转移保证了 $ f[i-1] $ 就是最优的。于是转移变成了 $ n^3 $ 但是数据范围告诉我们这样还不够。

  1. (买入): $ f[i][j]=max{~\sum_{k=1}^{k<j} f[i-1][k]-(j-k)\times AP[i]~} $
  2. (卖出): $ f[i][j]=max{~\sum_{k=1}^{k>j} f[i-1][k]+(k-j)\times BP[i]~} $

这两个式子其实把括号拆开后就是一个式子:

$ f[i][j]=max{~\sum_{k=1}^{k>j} f[i-1][k]+k\times P[i]-j\times P[i]~} $

单调队列优化: 我们发现我们买入卖出的式子是一个变量单调递增的,我们的 $ i $ 是最外层循环,在内层循环里它相当于定值,而我们的k和j在式子中是独立的,完全可以用单调队列维护 $ f[i-1][k]+k\times P[i] $ ,而 $ -j\times P[i] $ 就是定值,只需要来两次单调队列分别对应 $ AP[i] $ 和 $ BP[i] $ 即可。



$ code: $

#include<iostream>
#include<cstdio>
#include<iomanip>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<ctime>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set> #define ll long long
#define db double
#define inf 0x7fffffff
#define rg register int
#define max(A,B) (A>B?A:B) using namespace std; int n,m,w,l,r,now,a,b,c,d,ans;
int f[2001][2001],t[2001],p[2001]; inline int qr(){
char ch;
while((ch=getchar())<'0'||ch>'9');
int res=ch^48;
while((ch=getchar())>='0'&&ch<='9')
res=res*10+(ch^48);
return res;
} int main(){
//freopen("1.in","r",stdin);
//freopen(".out","w",stdout);
n=qr(),m=qr(),w=qr();
for(rg i=0;i<=n;++i)
for(rg j=0;j<=m;++j)
f[i][j]=-inf;
for(rg i=1;i<=n;++i){
a=qr(),b=qr();
c=qr(),d=qr();
for(rg j=0;j<=c;++j)
f[i][j]=-1*j*a;
for(rg j=0;j<=m;++j)
f[i][j]=max(f[i][j],f[i-1][j]);
if(i<=w)continue;
l=1;r=0;
for(rg j=0;j<=m;++j){
now=f[i-w-1][j]+j*a;
while(l<=r&&p[l]<j-c)++l;
while(l<=r&&t[r]<=now)--r;
t[++r]=now;p[r]=j;
if(l <= r)f[i][j]=max(f[i][j],t[l]-j*a);
}
l=1;r=0;
for(rg j=m;j>=0;--j){
now=f[i-w-1][j]+j*b;
while(l<=r&&p[l]>j+d)++l;
while(l<=r&&t[r]<=now)--r;
t[++r]=now;p[r]=j;
if(l <= r)f[i][j]=max(f[i][j],t[l]-j*b);
}
}
for(rg j=0;j<=m;++j)
ans=max(ans,f[n][j]);
printf("%d\n",ans);
return 0;
}

最新文章

  1. JavaScript中fn()和return fn()
  2. 别出心裁的Linux命令学习法
  3. iOS开发】canOpenURLl 和修改http请求
  4. HTML5使用Div标签来实现表格
  5. PHP获取搜索引擎关键字来源(百度、谷歌、雅虎、搜狗、搜搜、必应、有道)
  6. activiti_SpringEnvironment
  7. Android 动态生成布局 (多层嵌套)
  8. Camera服务之--架构浅析
  9. Struts2之Action接收请求参数和拦截器
  10. cin问题 分类: c++ 2014-08-02 21:13 38人阅读 评论(0) 收藏
  11. home目录迁移至新分区
  12. B-end
  13. Java面试题之对static的理解
  14. [LeetCode] Sliding Puzzle 滑动拼图
  15. C# Global.asax.cs 定时任务
  16. js-当前时间转换
  17. Mybash实现
  18. document.readyState等属性,判断页面是否加载完
  19. 2015 Noip提高组 Day1
  20. 剑指Offer(书):二维数组中的查找

热门文章

  1. C++ Primer 第四版阅读笔记
  2. mvn 与 pom.xml
  3. 网络处理器(Network Processor)
  4. bp文件错误消除
  5. 阶段1 语言基础+高级_1-3-Java语言高级_1-常用API_1_第4节 ArrayList集合_16-ArrayList练习一_存储随机数
  6. Matplotlib字体大小设置
  7. delphi备份恢复剪切板
  8. sprint test 添加事务回滚机制
  9. C语言作业总结
  10. 手把手教你用Pytorch-Transformers——部分源码解读及相关说明(一)