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

来源:互联网 发布:知乎看见了女朋友 编辑:程序博客网 时间:2024/05/22 17:10

单调队列入门题。。。

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 1000000009int 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;}


0 0
原创粉丝点击