zoukankan      html  css  js  c++  java
  • UESTC 880 生日礼物 --单调队列优化DP

    定义dp[i][j]表示第i天手中有j股股票时,获得的最多钱数。

    转移方程有:

    1.当天不买也不卖: dp[i][j]=dp[i-1][j];

    2.当天买了j-k股: dp[i][j]=max(dp[r][k]+(j-k)*Ap[i]); (r<i-w)

    3.当天卖了k-j股: dp[i][j]=max(dp[r][k]+(k-j)*Bp[i]); (r<i-w)

    直接转移复杂度太高,为O(n^2*Maxp^2).

    分别考虑每种转移,第一种不用管,考虑第二种。

    dp[i][j]=max(dp[r][k]+(j-k)*Ap[i])

    变换得:dp[i][j]-j*Ap[i]=dp[r][k]-k*Ap[i]。

    所以变成使dp[r][k]-k*Ap[i]最大。

    对于dp[r][k]-k*Ap[i], 因为我们已经有dp[i][k]=dp[i-1][k]的转移了,说明,dp[i][k]包含了所有dp[j][k] (j<i)的情况。 换句话说dp[i][k]是递增的。那么这里我们显然就可以直接把r换成i-w-1,于是变成了求 dp[i-w-1][k]-k*Ap[i]的最大值。

    令f[k]=dp[i-w-1][k]-k*Ap[i]) 原式变为 dp[i][j]=max(f[k])+j*Ap[i] (0=<k<j),如果再把与i相关的东西变成常数,则变成类似dp[j] = max(f[k])+c[j]形式,即变成可用单调队列优化的形式。

    维护一个单调递增队列来求f[k]。复杂度O(n*Maxp).

    因为直接令r=i-w-1,因为r>=1,所以i>w+1时才能转移,这是i<=w+1的情况需要预处理。

    代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #define Mod 1000000007
    using namespace std;
    #define N 2007
    
    struct node
    {
        int num,val;
    }que[N];
    
    int AP[N],BP[N],AS[N],BS[N];
    int dp[N][N];
    int n,Maxp,w;
    
    void init()
    {
        int i,j;
        for(i=0;i<=2000;i++)
            for(j=0;j<=Maxp;j++)
                dp[i][j] = -Mod;
        dp[0][0] = 0;
        for(i=1;i<=w+1;i++)
            for(j=0;j<=min(AS[i],Maxp);j++)
                dp[i][j] = -j*AP[i];
    }
    
    int main()
    {
        int i,j,k;
        int t,head,tail;
        scanf("%d",&t);
        while(t--)
        {
            scanf("%d%d%d",&n,&Maxp,&w);
            for(i=1;i<=n;i++)
                scanf("%d%d%d%d",&AP[i],&BP[i],&AS[i],&BS[i]);
            init();
            for(i=1;i<=n;i++)
            {
                //unbuy & unsell
                for(j=0;j<=Maxp;j++)
                    dp[i][j] = max(dp[i][j],dp[i-1][j]);
                if(i-w-1 <= 0)
                    continue;
                //buy j-k stocks
                head = 1;
                tail = 0;
                for(j=0;j<=Maxp;j++)
                {
                    int tmp = dp[i-w-1][j] + j*AP[i];
                    while(tail >= head && j-que[head].num > AS[i])
                        head++;
                    if(head <= tail)
                        dp[i][j] = max(dp[i][j],que[head].val-(j-que[head].num)*AP[i]);
                    while(tail >= head && que[tail].val+que[tail].num*AP[i] < tmp)
                        tail--;
                    que[++tail].num = j;
                    que[tail].val = dp[i-w-1][j];
                }
                //sell k-j stocks
                head = 1;
                tail = 0;
                for(j=Maxp;j>=0;j--)
                {
                    int tmp = dp[i-w-1][j] + j*BP[i];
                    while(tail >= head && que[head].num-j > BS[i])
                        head++;
                    if(head <= tail)
                        dp[i][j] = max(dp[i][j],que[head].val-(j-que[head].num)*BP[i]);
                    while(tail >= head && que[tail].val+que[tail].num*BP[i] < tmp)
                        tail--;
                    que[++tail].num = j;
                    que[tail].val = dp[i-w-1][j];
                }
            }
            int res = 0;
            for(i=0;i<=Maxp;i++)
                res = max(res,dp[n][i]);
            printf("%d
    ",res);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    easyExcel入门
    UML-从需求到设计--迭代进化
    UML-操作契约总结
    102. Binary Tree Level Order Traversal
    98. Validate Binary Search Tree
    95. Unique Binary Search Trees II
    96. Unique Binary Search Trees
    94. Binary Tree Inorder Traversal
    84. Largest Rectangle in Histogram
    92. Reverse Linked List II
  • 原文地址:https://www.cnblogs.com/whatbeg/p/3762737.html
Copyright © 2011-2022 走看看