HDU 3401 Trade

题意:

  给定每天的股票买进上限,买进价格,卖出上限,卖出价格,每两次买卖操作中间必须间隔w天,每天最多持有maxp个股票,问n天后最大收益是多少

题解:

  DP方程显然:

    dp[i][j]=max(不买不卖,买入操作,卖出操作)

 不买不卖
   dp[i][j]=max(dp[i][j],dp[i-1][j])
 买
   dp[i][j]=max(dp[pre][k]-(j-k)*AP[i])
   dp[i][j]+j*AP[i]=max(dp[pre][k]+k*AP[i])
   令f(k)=dp[i][k]+k*AP[i]
   f(j)=max(f(k)) (j-AS[i]<=k<=j)//经典单调队列
   所以dp[i][j]=f(j)-j*AP[i]
 卖
   dp[i][j]=max(dp[pre][k]+(k-j)*BP[[i])
   dp[i][j]+j*BP[i]=max(dp[pre][k]+k*BP[i])
   令ff(k)=dp[i][k]+k*AP[i]
   ff(j)=max(ff(k)) (j<=k<=j+BS[i])
   所以dp[i][j]=ff(j)-j*BP[i]

Note:两个过程要分开写 不然WAWAWA

代码:


#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;

const int N=2010;
const int inf=0x80808080;
typedef pair<int,int> PII;

int T;
int Time,MaxP,W;
int ap[N],bp[N],as[N],bs[N];

int dp[N][N];

PII que[N];
int st,ed;


int main() {
    scanf("%d",&T);
    while(T--) {
        memset(dp[0],inf,sizeof(dp[0]));
        dp[0][0]=0;
        scanf("%d%d%d",&Time,&MaxP,&W);
        for(int i=1;i<=Time;i++) scanf("%d%d%d%d",&ap[i],&bp[i],&as[i],&bs[i]);
        int ans=0;
        for(int i=1;i<=Time;i++) {
            memcpy(dp[i],dp[i-1],sizeof(dp[i]));
            if(i<=W+1) {
                for(int j=0;j<=as[i];j++) dp[i][j]=max(dp[i-1][j],-ap[i]*j);
                continue;
            }
            st=ed=0;
            int pre=i-W-1;
            //buy
            for(int j=0;j<=MaxP;j++) {
                PII elem=PII(dp[pre][j]+j*ap[i],j);
                que[ed++]=elem;
                while(ed-st>=1 && que[st].second<j-as[i]) st++;
                while(ed-st>=2 && que[ed-1].first>=que[ed-2].first) que[ed-2]=que[ed-1],ed--;
                dp[i][j]=max(dp[i][j],que[st].first-j*ap[i]);
                ans=max(ans,dp[i][j]);
            }
            st=ed=0;
            //sell
            for(int j=MaxP;j>=0;j--) {
                PII elem=PII(dp[pre][j]+j*bp[i],j);
                que[ed++]=elem;
                while(ed-st>=1 && que[st].second>j+bs[i]) st++;
                while(ed-st>=2 && que[ed-1].first>=que[ed-2].first) que[ed-2]=que[ed-1],ed--;
                dp[i][j]=max(dp[i][j],que[st].first-j*bp[i]);
                ans=max(ans,dp[i][j]);
            }

        }
        printf("%d\n",ans);
    }
    return 0;
}

 

posted @ 2012-08-29 17:12  编程菜菜  阅读(235)  评论(0编辑  收藏  举报