zoukankan      html  css  js  c++  java
  • 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;
    }

     

  • 相关阅读:
    全景转换工具
    Leetcode 215.数组中的第k个最大元素
    Leetcode 214.最短回文串
    Leetcode 213.大家劫舍II
    Leetcode 212.单词搜索II
    Leetcode 211.添加与搜索单词
    Leetcode 209.长度最小的子数组
    Leetcode 208.实现前缀树
    Leetcode 207.课程表
    Leetcode 206.反转链表
  • 原文地址:https://www.cnblogs.com/programCaiCai/p/HDU3401.html
Copyright © 2011-2022 走看看