luogu 2569 股票交易 单调队列dp

注意转移方程

分1.凭空买 2.不买不卖 3.在原来基础上买 4.在原来基础上卖 四种情况

head=1,tail=0;再判断一下head<=tail也可以

#include<bits/stdc++.h>
using namespace std;
const int N=2010;
int n,m,w,ans;
int ap[N],bp[N],as[N],bs[N];
int f[N][N];
int q[10000],head=1,tail=0;
int main()
{
    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]);

    memset(f,128,sizeof f);
    for(int i=0;i<=n;i++) f[i][0]=0;
    for(int i=1;i<=n;i++){
        for(int j=0;j<=as[i];j++) f[i][j]=-ap[i]*j;
        for(int j=m;j>=0;j--) f[i][j]=max(f[i][j],f[i-1][j]);
        if(i-w-1>=0)
        {
            head=1;tail=0;
            for(int j=0;j<=m;j++)
            {
                while(head<=tail&&q[head]<j-as[i]) head++;
                if(head<=tail) f[i][j]=max(f[i][j],f[i-w-1][q[head]]-ap[i]*(j-q[head]));
                while(head<=tail&&f[i-w-1][j]+ap[i]*j>=f[i-w-1][q[tail]]+ap[i]*q[tail]) tail--;
                q[++tail]=j;

            }
            head=1;tail=0;
            for(int j=m;j>=0;j--)
            {
                while(head<=tail&&q[head]>j+bs[i]) head++;
                if(head<=tail) f[i][j]=max(f[i][j],f[i-w-1][q[head]]+bp[i]*(q[head]-j));
                while(head<=tail&&f[i-w-1][j]+bp[i]*j>=f[i-w-1][q[tail]]+bp[i]*q[tail]) tail--;
                q[++tail]=j;

            }
        }
    }
    for(int i=0;i<=m;i++) ans=max(f[n][i],ans);
    printf("%d",ans);return 0;
}

原文地址:https://www.cnblogs.com/asdic/p/9693851.html

时间: 2024-10-11 20:08:10

luogu 2569 股票交易 单调队列dp的相关文章

POJ 3017 单调队列dp

Cut the Sequence Time Limit: 2000MS   Memory Limit: 131072K Total Submissions: 8764   Accepted: 2576 Description Given an integer sequence { an } of length N, you are to cut the sequence into several parts every one of which is a consecutive subseque

[TyvjP1313] [NOIP2010初赛]烽火传递(单调队列 + DP)

传送门 就是个单调队列+DP嘛. ——代码 1 #include <cstdio> 2 3 const int MAXN = 1000001; 4 int n, m, h = 1, t = 1, ans = ~(1 << 31); 5 int q[MAXN], a[MAXN], f[MAXN]; 6 7 inline int min(int x, int y) 8 { 9 return x < y ? x : y; 10 } 11 12 int main() 13 { 14

hdu4374单调队列+dp

http://acm.hdu.edu.cn/showproblem.php?pid=4374 Problem Description Now there is a game called the new man down 100th floor. The rules of this game is: 1.  At first you are at the 1st floor. And the floor moves up. Of course you can choose which part

LUOGU P2569 [SCOI2010]股票交易(单调队列优化dp)

传送门 解题思路 不难想一个\(O(n^3)\)的\(dp\),设\(f_{i,j}\)表示第\(i\)天,手上有\(j\)股的最大收益,因为这个\(dp\)具有单调性,所以\(f_i\)可以贪心的直接从\(f_{i-w-1}\)那一层转移来,转移时枚举一下当前买卖多少.考虑优化,发现每次其实就是一个区间取\(max\),是由\(AS\)和\(BS\)所限制的区间,所以单调队列优化就好了,一个正着做一个倒着做,时间复杂度\(O(n^2)\) 代码 #include<bits/stdc++.h>

1855: [Scoi2010]股票交易[单调队列优化DP]

1855: [Scoi2010]股票交易 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 1083  Solved: 519[Submit][Status][Discuss] Description 最近lxhgww又迷上了投资股票,通过一段时间的观察和学习,他总结出了股票行情的一些规律. 通过一段时间的观察,lxhgww预测到了未来T天内某只股票的走势,第i天的股票买入价为每股APi,第i天的股票卖出价为每股BPi(数据保证对于每个i,都有APi>=

bzoj1855: [Scoi2010]股票交易--单调队列优化DP

单调队列优化DP的模板题 不难列出DP方程: 对于买入的情况 由于dp[i][j]=max{dp[i-w-1][k]+k*Ap[i]-j*Ap[i]} AP[i]*j是固定的,在队列中维护dp[i-w-1][k]+k*Ap[i]的单调性即可 1 #include<stdio.h> 2 #include<string.h> 3 #include<algorithm> 4 using namespace std; 5 const int maxn = 2010; 6 int

BZOJ 1855 [Scoi2010]股票交易 单调队列优化DP

题意:链接 方法:单调队列优化DP 解析:噢又是一道情况很多的题,然而三种更新我又落下一种导致样例不过,后来看题解才恍然- -最SB的一种更新居然忘了. 状态好想f[i][j]代表前i天有j双袜子时的最大利润. 三种更新: 第一种:f[i][j]=max(f[i][j],f[i?1][j]):(然而我忘了这一种) 第二种:买入f[i][j]=max(f[i][j],f[i?w?1][k]?(j?k)?a[i].ap)(k>=j?a[i].as); 第三种:卖出f[i][j]=max(f[i][j

AcWing - 332 - 股票交易 = 单调队列优化dp

https://www.acwing.com/problem/content/334/ 第一次写单调队列优化的dp,首先朴素的做法不难想到,就是复杂度 \(O(n^3)\) ,然后考虑优化. 每天都从 \(pre=max(0,i-w-1)\) 天转移过来就刚刚好了. 考虑每个k是怎么更新j的. 买入股票: \(dp[i][j]=max\{dp[pre][k]-(j-k)*AP_i\;|\;k \leq j\;and\;(j-k) \leq AS_i\}\) \(dp[i][j]=max\{dp[

【bzoj1855||hdu3401】股票交易——单调队列优化dp

代码基本是跟着yy dalao码的吧, 主要是要知道单调队列优化要怎么做, f[i][j]表示第i天手里有j股时的收益. 从第一天到第w+1天初始化为-e[i].ap*j(因为此时只能买不能卖),其余为-inf. 分三种情况: 1.不买不卖:即f[i][j]=max(f[i][j],f[i-1][j]); 2.买进: f[i][j]=max(f[i-W-1][k]-(j-k)*e[i].ap,f[i][j]).在这里j-e[i].as<k<=mxa,利用f[i][j]=max(f[i-W-1]