• hdu 3401(单调队列优化dp)


    注意:这题题意是有操作的天数相隔要大于w

    然后列出状态转移方程就可以发现,可以用优点队列优化啦。

    构造状态dp[i][j]表示第i 天拥有 j只股票的时候,赚了多少钱

    状态转移有:

    1、从前一天不买不卖:

    dp[i][j]=max(dp[i-1][j],dp[i][j])

    2、从前i-W-1天买进一些股:

    dp[i][j]=max(dp[i-W-1][k]-(j-k)*AP[i],dp[i][j])

    3、从i-W-1天卖掉一些股:

    dp[i][j]=max(dp[i-W-1][k]+(k-j)*BP[i],dp[i][j])

    //
    //  main.cpp
    //  hdu3401
    //
    //  Created by New_Life on 16/8/16.
    //  Copyright © 2016年 chenhuan001. All rights reserved.
    //
    
    #include <iostream>
    #include <stdio.h>
    #include <algorithm>
    #include <queue>
    #include <string.h>
    #include <string>
    using namespace std;
    
    #define N 2020
    #define INF 100000000
    
    /******************_单调队列模板_******************/
    //基于单调队列功能的单一性:以limit为序查找在一定范围内的极值。
    //复杂度:O(n)
    //用法: 创建的时候调用.init()
    //      插入队列:.push( Q_Node( KEY,LIMIT ) );
    //      设置limit值:.setlimit( LIMIT );
    //      查询<limit值的最大元素: Q_Node qn; q2.top(qn);
    //      再查询前需要设置limit值,如果队列为空返回false,否则将最大元素存入qn中并返回true
    
    struct Q_Node {
        int key,limit;//用来比较大小的key和控制存在时间的limit
        Q_Node(){}
        Q_Node(int _key,int _limit){ key=_key,limit=_limit; }
    };
    
    
    struct Q_Que {
        Q_Node Q[N];
        int qf,qd;
        int limit;// <limit 的元素将被弹出
        void init() {
            qf = qd = 0;//将队列内元素清空
        }
        
        void push(Q_Node newnode) {//默认入队是当前limit最大的
            while (qf>qd && Q[qf-1].key < newnode.key) qf--;
            Q[qf++] = newnode;
        }
        
        void setlimit(int _limit) {
            limit = _limit;
        }
        
        /*
         取出队列中>=limit且key最大的元素。
         */
        bool top(Q_Node &rt)
        {
            while(qf>qd && Q[qd].limit < limit) qd++;
            if(qf==qd) return false;
            rt = Q[qd];
            return true;
        }
    }q1,q2;
    
    
    
    
    int dp[N][N];
    int ap[N],bp[N],as[N],bs[N];
    
    int main(int argc, const char * argv[]) {
        int T;
        cin>>T;
        while(T--)
        {
            int t,mxp,w;
            cin>>t>>mxp>>w;
            for(int i=1;i<=t;i++) scanf("%d%d%d%d",ap+i,bp+i,as+i,bs+i);
            
            for(int i=0;i<=t;i++)
                for(int j=0;j<=mxp;j++) dp[i][j] = -INF;
            for(int i=1;i<=w+1;i++)
                for(int j=0;j<=as[i];j++)
                    dp[i][j] = -j*ap[i];
            dp[0][0] = 0;
            for(int i=1;i<=t;i++)
            {
                q1.init(); q2.init();
                int sum1=0,sum2=0;
                for(int j=0;j<=mxp;j++)
                {
                    dp[i][j] = max(dp[i][j],dp[i-1][j]);//啥也没做
                }
                
                if(i <= w+1) continue;
                for(int j=0;j<=mxp;j++)
                {
                    q1.push( Q_Node(dp[i-w-1][j]-sum1,j) );
                    q1.setlimit(j-as[i]);
                    Q_Node qn;
                    if(q1.top(qn))
                    {
                        dp[i][j] = max(dp[i][j],qn.key+sum1);
                    }
                    sum1 -= ap[i];
                }
                
                for(int j=mxp;j>=0;j--){
                    q2.push(Q_Node(dp[i-w-1][j]-sum2, -j));
                    q2.setlimit(-j-bs[i]);
                    Q_Node qn;
                    if(q2.top(qn)) dp[i][j] = max(dp[i][j],qn.key+sum2);
                    sum2 += bp[i];
                }
                
            }
            int ans = 0;
            for(int i=1;i<=t;i++)
                for(int j=0;j<=mxp;j++) ans= max(ans,dp[i][j]);
            cout<<ans<<endl;
        }
        return 0;
    }
    /*
     20
     5 2 0
     2 1 1 1
     2 1 1 1
     3 2 1 1
     4 3 1 1
     5 4 1 1
     5 3 0
     2 1 2 2
     2 1 12 1
     3 2 2 1
     4 3 3 2
     5 4 1 2
     5 2 3
     2 1 3 2
     1 1 12 1
     3 2 2 2
     4 3 3 3
     5 4 1 2
     5 3 3
     2 1 3 2
     1 1 12 1
     3 4 2 2
     1 3 3 3
     1 3 3 5
     5 10 0
     2 1 3 2
     1 1 12 1
     3 4 2 2
     1 3 3 3
     1 3 3 5
     5 10 0
     2 1 3 2
     1 1 12 0
     3 4 4 2
     1 3 0 3
     1 3 0 5
     4 1 1
     1 1 1 1
     1 1 1 1
     1 3 1 1
     1 3 1 1
     
     10
     4 3 1
     3 1 1 1
     5 1 1 1
     10 6 1 1
     10 6 1 1
     
     */
  • 相关阅读:
    一、NHibernate 使用配置与实现简单查询
    NHibernate学习步骤
    sql2008转成2005的解决办法
    二、使用NHibernate对数据库实现增、删、改、查操作
    FusionCharts 点击事件 新页面
    [分享]NHibernate视频教程
    FusionCharts Free使用文档教程第五章FusionCharts Free使用dataXML加载数据
    职业规划
    网页生成pdf文件
    FusionCharts Free使用文档教程第四章FusionCharts Free使用JavaScript加载图形
  • 原文地址:https://www.cnblogs.com/chenhuan001/p/5782049.html
Copyright © 2020-2023  润新知