zoukankan      html  css  js  c++  java
  • 【HDU】3401:Trade【单调队列优化DP】

    Trade

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 5864    Accepted Submission(s): 2022


    Problem Description
    Recently, lxhgww is addicted to stock, he finds some regular patterns after a few days' study.
    He forecasts the next T days' stock market. On the i'th day, you can buy one stock with the price APi or sell one stock to get BPi.
    There are some other limits, one can buy at most ASi stocks on the i'th day and at most sell BSi stocks.
    Two trading days should have a interval of more than W days. That is to say, suppose you traded (any buy or sell stocks is regarded as a trade)on the i'th day, the next trading day must be on the (i+W+1)th day or later.
    What's more, one can own no more than MaxP stocks at any time.

    Before the first day, lxhgww already has infinitely money but no stocks, of course he wants to earn as much money as possible from the stock market. So the question comes, how much at most can he earn?
     
    Input
    The first line is an integer t, the case number.
    The first line of each case are three integers T , MaxP , W .
    (0 <= W < T <= 2000, 1 <= MaxP <= 2000) .
    The next T lines each has four integers APi,BPi,ASi,BSi( 1<=BPi<=APi<=1000,1<=ASi,BSi<=MaxP), which are mentioned above.
     
    Output
    The most money lxhgww can earn.
     
    Sample Input
    1 5 2 0 2 1 1 1 2 1 1 1 3 2 1 1 4 3 1 1 5 4 1 1
     
    Sample Output
    3
     
    Author
    lxhgww
     
    Source
     
    Recommend
    lcy

    Solution

    题目大意是股票在$t$天内每天买或卖或不作为,知道每一天每一支股票的买卖价格$api,bpi$和限购或卖的量$asi,bsi$,以及每天最多持有的股票数$maxp$,还有每次交易必须隔至少$w$的限制,求最大的收益。

    DP式定义为$dp[i][j]$表示在第$i$天持有$j$张股票的最大收益。

    转移有三方面:

    1、不作为:$dp[i][j]=dp[i-1][j]$(所以转移2、3时不用考虑$i-w-1$天前)

    2、买进:$dp[i][j]=dp[i-w-1][k]-(j-k)*api=>max(dp[i-w-1][k]+k*api)-j*api$

    3、卖出:$dp[i][j]=dp[i-w-1][k]+(k-j)*bpi=>max(dp[i-w-1][k]+k*bpi)-j*bpi$

    观察2、3,发现max部分就是单调队列的结构,所以每次对于j找最优决策点(并且满足每天的各种限制),将$n^3$压成了$n^2$。

    Code

     

    #include<bits/stdc++.h>
    #define inf 0x3f3f3f3f
    using namespace std;
    
    int t, maxp, w;
    int dp[2005][2005], ap[2005], as[2005], bp[2005], bs[2005];
    
    struct Node {
        int num, m;
    } q[2005];
    
    int main() {
        int T;
        scanf("%d", &T);
        while(T --) {
            scanf("%d%d%d", &t, &maxp, &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 <= maxp; j ++)    dp[i][j] = -inf;
            for(int i = 1; i <= w + 1; i ++)
                for(int j = 0; j <= min(maxp, as[i]); j ++)
                    dp[i][j] = -j * ap[i];
            dp[0][0] = 0;
            for(int i = 1; i <= t; i ++) {
                for(int j = 0; j <= maxp; j ++) {
                    dp[i][j] = max(dp[i][j], dp[i - 1][j]);
                }
                if(i - w - 1 <= 0)    continue;
                int pre = i - w - 1;
                int h = 1, t = 0;
                for(int j = 0; j <= maxp; j ++) {
                    int f = dp[pre][j] + ap[i] * j;
                    while(h <= t && q[t].m <= f)     t --;
                    q[++ t].num = j;
                    q[t].m = f;
                    while(h <= t && q[h].num + as[i] < j)    h ++;
                    dp[i][j] = max(dp[i][j], q[h].m - ap[i] * j);
                }
                h = 1; t = 0;
                for(int j = maxp; j >= 0; j --) {
                    int f = dp[pre][j] + bp[i] * j;
                    while(h <= t && q[t].m <= f)    t --;
                    q[++ t].num = j;
                    q[t].m = f;
                    while(h <= t && q[h].num - bs[i] > j)    h ++;
                    dp[i][j] = max(dp[i][j], q[h].m - bp[i] * j);
                }
            }
            int res = -inf;
            for(int i = 0; i <= maxp; i ++)    res = max(res, dp[t][i]);
            printf("%d
    ", res);
        }
        return 0;
    }

     

     

  • 相关阅读:
    linux下安装rpc.rstatd
    myeclipse下编译jmeter2.4
    2010我最喜爱的耳机评选结果q
    HTTP/1.1 Range和ContentRange
    top命令的load average是什么意思?
    用户 'sa' 登录失败。该用户与可信 SQL Server 连接无关联。
    自定义ListBox,实现单多选切换(复选框)
    自定义水印输入框和密码框
    获取Windows Phone设备信息
    启动器和选择器学习(7)选择器之联系人信息保存
  • 原文地址:https://www.cnblogs.com/wans-caesar-02111007/p/9832274.html
Copyright © 2011-2022 走看看