题意:

已知未来 N 天的股票走势,第 i 天最多买进 as [ i ] 股每股 ap [ i ] 元,最多卖出 bs [ i ] 股每股 bp [ i ] 元,且每天最多拥有 Mp 股,且每两次交易至少需要相隔 W 天,求最多能赚多少钱。

细节:

1、初始情况下有无限的资金,但是不能算作赚的钱。

2、对于交易的定义为:买进一次股或者买出一次股,也就是不能在同一天进行两种操作。

分析:

这题目根据题意不难发现它必定存在重复子结构,而且对于后面买卖股票的过程不会影响前方的收益情况,可以得到这可以用动态规划解决。

状态的构建也是显然的:dp [ i ][ j ] 表示第 i 天拥有 j 股的最大价值。

1、初值->负无穷???

若是 0 则在转移的时候将不会出现在没有赚钱的情况下去买股票的情况。

且每个可行状态 dp [ i ][ j ] = -ap [ i ] × j ( 0 ⩽ j ⩽ as [ i ] )

2、当前不买也不卖-> dp [ i ][ j ] = max ( dp [ i - 1 ][ j ], dp[ i ][ j ] )

3、当前需要买进股票,由于有 W 天间隔的限制,所以不难发现我们需要枚举当前这次贸易需要从哪一次交易转移而来,但是由于有第二类情况的存在,其实第 0 至 i - W - 1 这几天的交易最优值是单调不降的,所以最优的价值一定可以从 i - W - 1 天的状态转移而来,所以转移:

dp [ i ][ j ] = max ( dp [ i ][ j ] , dp[ i - W - 1 ][ k ] - ( j - k ) × ap [ i ] )

( max ( 0 , j - as [ i ] ) ⩽ k ⩽ j )

4、当前需要卖出股票,转移就是:

dp [ i ][ j ] = max ( dp [ i ][ j ] , dp[ i - W - 1 ][ k ] + ( k - j ) × bp [ i ] )

( j ⩽ k ⩽ min( Mp , j + bs [ i ] ) )

成功的写出了朴素的动态规划方程,现在考虑优化,由于 N ≤ 2000Mp ≤ 2000 这个 2D / 1D 的动态规划显然不能 AC ,比如把 3 的式子进行转化:

dp [ i ][ j ] = max { dp [ i - W - 1][ k ] + k × ap [ i ] } - j × ap [ i ]

显然又转化成一个定区间求最值的模型,就可以使用单调队列解决了,4 式的转化同理可得,在转移时可以令 jMp 开始往 0 进行转移,按序加入队列中。

代码:

#include<bits/stdc++.h>
#define Inf 1000000000
#define MAXN 2005
using namespace std; int f[MAXN][MAXN], ap[MAXN], bp[MAXN], as[MAXN], bs[MAXN];
int n, Mp, w, que1[MAXN], que2[MAXN]; int main(){
scanf("%d%d%d", &n, &Mp, &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<=Mp; j++) f[i][j]=-Inf;
for (int i=1; i<=n; i++)
for (int j=0; j<=as[i]; j++) f[i][j]=-j*ap[i];
for (int i=1; i<=n; i++){
for (int j=0; j<=Mp; j++) f[i][j]=max(f[i][j], f[i-1][j]);
int head1=1, head2=1, tail1=0, tail2=0;
for (int j=0; j<=Mp; j++){
while (head1<=tail1 && que1[head1]<max(j-as[i], 0)) ++head1;
if (head1<=tail1) f[i][j]=max(f[i][j], f[max(0, i-w-1)][que1[head1]]-(j-que1[head1])*ap[i]);
while (head1<=tail1 && f[max(i-w-1, 0)][que1[tail1]]+que1[tail1]*ap[i]<=f[max(i-w-1, 0)][j]+j*ap[i]) --tail1;
que1[++tail1]=j;
}
for (int j=Mp; j>=0; j--){
while (head2<=tail2 && que2[head2]>min(Mp, j+bs[i])) ++head2;
if (head2<=tail2) f[i][j]=max(f[i][j], f[max(0, i-w-1)][que2[head2]]+(que2[head2]-j)*bp[i]);
while (head2<=tail2 && f[max(i-w-1, 0)][que2[tail2]]+que2[tail2]*bp[i]<=f[max(0, i-w-1)][j]+j*bp[i]) --tail2;
que2[++tail2]=j;
}
}
int Ans=-Inf;
for (int i=0; i<=Mp; i++) Ans=max(Ans, f[n][i]);
printf("%d\n", Ans);
return 0;
}

最新文章

  1. Ubuntu搭建NFS
  2. nginx下搭建CodeIgniter问题集锦
  3. ajax+php+js实现异步刷新表单验证
  4. DELPHI实现关闭指定进程,自身防杀
  5. 菜鸟学Android编程——简单计算器《一》
  6. MVC4之ModelBinder-模型绑定
  7. 使用Arcglobe 10与3dmax建立三维城市
  8. 如何解决在GDI画图中,多次修改画笔的颜色
  9. 调试exynos4412—ARM嵌入式Linux—LEDS/GPIO驱动之二
  10. c#1所搭建的核心基础之委托
  11. Private和Protected方法
  12. Linux之解决你的网络问题
  13. css中bfc和ifc
  14. Converting PDF to Text in C#
  15. H5新特性---Web Worker---Web Stroage
  16. linux下静态库和动态库的制作
  17. Java 并发工具包 | J.U.C
  18. 用IntelliJ IDEA编译,编译之后提示 无效的标记: -release
  19. ajax 调用 java webapi 多个参数(一)
  20. CentOS6.4下邮件服务器搭建

热门文章

  1. morhpia(4)-更新
  2. base64 正则表达式 ,判断图片是base64还是图片链接
  3. #82. 【UR #7】水题生成器
  4. pc端_移动端_H5_ QQ在线客服链接代码
  5. js中函数的理解
  6. python部分 + 数据库 + 网络编程
  7. Android 麦克风录音带音量大小动态显示的圆形自定义View
  8. IOS自动化测试之UIAutomation
  9. Grace Huang 2017/1/11
  10. hihoCoder #1070 : RMQ问题再临