zoukankan      html  css  js  c++  java
  • 洛谷P2569 股票交易【dp】【单调队列】

    题目描述

    最近  ext{lxhgww}lxhgww 又迷上了投资股票,通过一段时间的观察和学习,他总结出了股票行情的一些规律。

    通过一段时间的观察, ext{lxhgww}lxhgww 预测到了未来 TT 天内某只股票的走势,第 ii 天的股票买入价为每股 AP_iAPi,第 ii 天的股票卖出价为每股 BP_iBPi(数据保证对于每个 ii,都有 AP_i geq BP_iAPiBPi),但是每天不能无限制地交易,于是股票交易所规定第 ii 天的一次买入至多只能购买 AS_iASi 股,一次卖出至多只能卖出 BS_iBSi 股。

    另外,股票交易所还制定了两个规定。为了避免大家疯狂交易,股票交易所规定在两次交易(某一天的买入或者卖出均算是一次交易)之间,至少要间隔 WW 天,也就是说如果在第 ii 天发生了交易,那么从第 i+1i+1 天到第 i+Wi+W 天,均不能发生交易。同时,为了避免垄断,股票交易所还规定在任何时间,一个人的手里的股票数不能超过  ext{MaxP}MaxP。

    在第 11 天之前, ext{lxhgww}lxhgww 手里有一大笔钱(可以认为钱的数目无限),但是没有任何股票,当然,TT 天以后, ext{lxhgww}lxhgww 想要赚到最多的钱,聪明的程序员们,你们能帮助他吗?

    输入输出格式

    输入格式:

    输入数据第一行包括 33 个整数,分别是 TT, ext{MaxP}MaxP,WW。

    接下来 TT 行,第 ii 行代表第 i-1i1 天的股票走势,每行 44 个整数,分别表示 AP_i, BP_i, AS_i, BS_iAPi, BPi, ASi, BSi

    输出格式:

    输出数据为一行,包括 11 个数字,表示  ext{lxhgww}lxhgww 能赚到的最多的钱数。

    输入输出样例

    输入样例#1: 复制
    5 2 0
    2 1 1 1
    2 1 1 1
    3 2 1 1
    4 3 1 1
    5 4 1 1
    
    输出样例#1: 复制
    3

    说明

    对于 30\%30% 的数据,0leq W<Tleq 50,1leq ext{MaxP}leq500W<T50,1MaxP50

    对于 50\%50% 的数据,0leq W<Tleq 2000,1leq ext{MaxP}leq500W<T2000,1MaxP50

    对于 100\%100% 的数据,0leq W<Tleq 2000,1leq ext{MaxP}leq20000W<T2000,1MaxP2000

    对于所有的数据,1leq BP_ileq AP_ileq 1000,1leq AS_i,BS_ileq ext{MaxP}1BPiAPi1000,1ASi,BSiMaxP

    题意:

    一共t天,最多可以持有maxp支股票。给定每天股票买入卖出价格和每天的交易限额。问可以最多赚多少钱。

    思路:

    应该能够想得到这是一个dp。子结构就是前i天能赚取的最多价格,这就是“阶段”,也就是第一维。同时我们还需要记录一下持有的股票数,因为状态转移时,不同的股票数的转移是不同的。

    因此,dp[i][j]表示第i天持有j的时候所能赚取的最大值。

    对于每一天我们都有三种情况。

    1.不买也不卖。 那么转移方程就是

    2.买入。买入有分两种情况,一种是之前什么都没有,这j股都是在第i天买的。

      另一种是之前的某一天买了k股,今天买了j-k股。而且题目要求两个交易的日子要间隔w天。

    3.卖出。之前的某一天有k股,卖掉了k-j股,第i天剩下j股。

    但是我们会发现状态转移的时候如果枚举k,会出现O(n^3)的复杂度,需要进一步优化。

    观察状态转移方程我们可以把k合并同类项,比如卖出的式子可以变成

    由于max{}中的是一个正数,假设我们设在j时这个值为x,扩展到j+1时,我们只有可能取x或者k=j时的值。他是一个递增的选择。

    就可以用单调队列来维护这个值了。

    由于卖出是由比j大的k推出的,所以在转移卖出这种情况的时候,j应该是逆序的。

     1 #include <iostream>
     2 #include <set>
     3 #include <cmath>
     4 #include <stdio.h>
     5 #include <cstring>
     6 #include <algorithm>
     7 #include <vector>
     8 #include <queue>
     9 #include <map>
    10 #include <bits/stdc++.h>
    11 using namespace std;
    12 typedef long long LL;
    13 #define inf 0x7f7f7f7f
    14 
    15 const int maxn = 2005;
    16 int t, maxp, w;
    17 struct node{
    18     int ap, bp, as, bs;
    19 }day[maxn];
    20 int dp[maxn][maxn], que[maxn];
    21 
    22 int main()
    23 {
    24     scanf("%d%d%d", &t, &maxp, &w);
    25     memset(dp, -inf, sizeof(dp));
    26     for(int i = 1; i <= t; i++){
    27         scanf("%d%d%d%d", &day[i].ap, &day[i].bp, &day[i].as, &day[i].bs);
    28     }
    29     for(int i = 1; i <= t; i++){
    30         for(int j = 0; j <= day[i].as; j++){
    31             dp[i][j] = -j * day[i].ap;
    32         }
    33         for(int j = 0; j <= maxp; j++){
    34             dp[i][j] = max(dp[i][j], dp[i - 1][j]);
    35         }
    36         if(i <= w)continue;
    37         int head = 1, tail = 0;
    38         for(int j = 0; j <= maxp; j++){
    39             while(dp[i - w - 1][que[tail]] + que[tail] * day[i].ap <= dp[i - 1 - w][j] + j * day[i].ap && head <= tail){
    40                 tail--;
    41             }
    42             que[++tail] = j;
    43             while(j - que[head] > day[i].as){
    44                 head++;
    45             }
    46             dp[i][j] = max(dp[i][j], dp[i - w - 1][que[head]] - (j - que[head]) * day[i].ap);
    47         }
    48 
    49         head = 1, tail = 0;
    50         for(int j = maxp; j >= 0; j--){
    51             while(dp[i - w - 1][que[tail]] + que[tail] * day[i].bp <= dp[i - 1 - w][j] + j * day[i].bp && head <= tail){
    52                 tail--;
    53             }
    54             que[++tail] = j;
    55             while(que[head] - j > day[i].bs){
    56                 head++;
    57             }
    58             dp[i][j] = max(dp[i][j], dp[i - 1 - w][que[head]] + (que[head] - j) * day[i].bp);
    59         }
    60     }
    61 
    62 
    63     int ans = -1;
    64     for(int j = 0; j <= maxp; j++){
    65         ans = max(ans, dp[t][j]);
    66     }
    67     printf("%d
    ", ans);
    68     return 0;
    69 }
  • 相关阅读:
    Log4j appender、layout
    EhCache缓存框架的使用
    Log4j rootLogger根配置以及4种日志级别
    开发chrome 插件, background.js中 console log 看不到解决方法
    Windows cmd 长时间不输出新内容 直到按下ctrl + c 取消或者回车的解决办法
    如何查看当前分支从哪个支线创建而来
    C# 获取相对路径的字符串
    解决adobe air sdk打包 apk后自动在包名前面加上air. (有个点)前缀的问题
    sublime text 输入法候选词不跟随光标
    Windows 批处理设置dns ,解决能上qq不能开网页
  • 原文地址:https://www.cnblogs.com/wyboooo/p/9888920.html
Copyright © 2011-2022 走看看