hdu-3401-Trade-单调队列优化的DP

单调队列入门题。。。

dp[i][j]:第i天。手中拥有j个股票时,获得的最大利润。

若第i天不买不卖:dp[i][j]=max(dp[i][j],dp[i-1][j]);

若第i天买            :dp[i][j]=max(dp[i][j],dp[i-w-1][k]-(j-k)*ap[i]);

若第i天卖            :dp[i][j]=max(dp[i][j],dp[i-w-1][k]+(k-j)*bp[i]);

若仅仅考虑买的情况:

dp[i][j]=dp[i-w-1][k]+ap[i]*k-j*ap[i];

非常明显。能够用单调队列优化dp[i-w-1][k]+ap[i]*k。

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<queue>
using namespace std;
//#define INF ((1<<30)-1)
#define INF 0xfffff
#define maxn 2200
#define LL long long
#define MOD 1000000009
int dp[2200][2200];
struct list
{
    int val;
    int x;
} p[5001],q;
int ap[maxn],bp[maxn],as[maxn],bs[maxn];
int main()
{
    int Ts;
    int n,m,w,i,j;
    scanf("%d",&Ts);
    while(Ts--)
    {
        scanf("%d%d%d",&n,&m,&w);
        for(i=0; i<=n; i++)
            for(j=0; j<=m; j++)dp[i][j]=-INF;
        int head,tail;
        for(i=1;i<=n;i++)scanf("%d%d%d%d",&ap[i],&bp[i],&as[i],&bs[i]);
        for(j=1;j<=w+1;j++)
            for(i=0;i<=min(as[j],m);i++)
                dp[j][i]=-1*ap[j]*i;
        for(i=2; i<=n; i++)
        {
            for(j=0;j<=m;j++)dp[i][j]=max(dp[i-1][j],dp[i][j]);
            if(i<=w+1)continue;
            head=1;
            tail=0;
            for(j=0; j<=m; j++)
            {
                q.x=j;
                q.val=dp[i-w-1][j]+ap[i]*j;
                while(tail>=head&&q.val>p[tail].val)tail--;
                p[++tail]=q;
                while(tail>=head&&p[head].x<j-as[i])head++;
                if(head<=tail)dp[i][j]=max(dp[i][j],p[head].val-ap[i]*j);
            }
            head=1;
            tail=0;
            for(j=m;j>=0;j--)
            {
                q.x=j;
                q.val=dp[i-w-1][j]+bp[i]*j;
                while(tail>=head&&q.val>p[tail].val)tail--;
                p[++tail]=q;
                while(tail>=head&&p[head].x>j+bs[i])head++;
                if(head<=tail)dp[i][j]=max(dp[i][j],p[head].val-bp[i]*j);
            }
        }
        int maxx=0;
        for(i=0;i<=m;i++)maxx=max(maxx,dp[n][i]);
        printf("%d\n",maxx);
    }
    return 0;

}
时间: 2024-08-07 16:41:20

hdu-3401-Trade-单调队列优化的DP的相关文章

HDU 3401 Trade(单调队列优化)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3401 题意:炒股.第i天买入一股的价钱api,卖出一股的价钱bpi,最多买入asi股,最多卖出bsi股.两次操作(买入或卖出)中间必须相差W天.炒股时间为n.任意时间手中的股票不大于MaxP.求最大收益. dp[i][j]代表第i天手上有j股的最大收益,dp[i][j]=max(dp[i-1][j],dp[i-W][k]+(j-k)*ap[i],dp[i-W][k]+(k-j)*bp[i]); dp

hdu3401 Trade(单调队列优化dp)

Trade Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 4734    Accepted Submission(s): 1587 Problem Description Recently, lxhgww is addicted to stock, he finds some regular patterns after a few d

HDU 3401 Trade(斜率优化dp)

http://acm.hdu.edu.cn/showproblem.php?pid=3401 题意:有一个股市,现在有T天让你炒股,在第i天,买进股票的价格为APi,卖出股票的价格为BPi,同时最多买进股票的数量为ASi,卖出股票的数量为BSi.一次交易之后要隔W天之后才能再次交易,并且手上最多持股maxP,问最多可以炒到多少钱. 思路: 首先列一个DP方程: 分别代表不买不卖,买进股票,卖出股票三种情况(上面 (j-k)<=AS[i] , (k-j)<=BS[i]). 那么这里需要枚举r和k

单调队列优化的DP

(持续更新中--) 一.浅谈单调队列之多重背包   前言:首先标题起了一个很优雅的名字,貌似很高深的样子,其实不然,只是把自己理解的记录一下而已. 多重背包的状态转移方程:dp[ i ]  [ j ]  =  max ( dp[ i - 1 ] [ j ]  , dp[ i - 1 ] [ j - k * v[ i ] ] + k * w[ i ]  } (  0 <= k <= num[ i ])  ;  先说一下多重背包的二进制解法,因为大多数的题目都可以用此方法解决:复杂度( num[

HDU 3507 PrintArticle (单调队列优化)

题意:给出一个数列C,一个数字M,将数列分成若干段,每段的代价为(设这段的数字为k个): dp[i]=min(dp[j]+(sum[i]-sum[j])*(sum[i]-sum[j])+M) 若j1<j2且j2比j1优 dp[j1]+sum[i]^2+sum[j1]^2-2*sum[i]*sum[j1]+M>dp[j2]+sum[i]^2+sum[j2]^2-2*sum[i]*sum[j2] dp[j1]-dp[j2]+sum[j1]^2-sum[j2]^2>2*sum[i]*(sum[

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[

HDU 3401 Trade dp 单调队列优化

戳这里:3401 题意:给出第 i 天的股票买卖价格(APi,BPi),以及每天股票买卖的数量上限(ASi,BSi),要求任两次交易需要间隔 W 天以上,即第 i 天交易,第 i + W + 1 天才能再交易,求最多能赚多少钱 思路:dp[i][j] = max(dp[i - 1][j], max(dp[f][k] - (j - k) * APi[i]), max(dp[f][k] + (k - j) * BPi[i])); 从式子中观察出,若两天都持有股票数 j 时,之后的那一天所赚的钱不小于

HDU 4122 Alice&#39;s mooncake shop 单调队列优化dp

Alice's mooncake shop Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=4122 Description The Mid-Autumn Festival, also known as the Moon Festival or Zhongqiu Festival is a popular harvest festival celebrated by Ch

HDU 4374 One hundred layer(单调队列优化dp)

题意:有一个n*m的矩阵,每格有一个分数,一个人站在(1,x)位置,在每一行中,他只能朝一个方向走(向左或向右),且最多走t步,问走到最后第n行得到的最大分数. 思路:不难想到状态转移方程dp[i][j] = max(dp[i-1][k]+sum[i][j]-sum[i][k-1]),(k<j) 移项得 dp[i][j]-sum[i][j] = max(dp[i-1][k] - sum[i][k-1]); 方程右侧与i,j无关,所以可以用单调队列维护max(dp[i-1][k] - sum[i]

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>=