hdu 3401 单调队列优化动态规划

思路:

动态方程很容易想到dp[i][j]=max(dp[i][j],dp[i-w-1][j-k]-k*ap[i],dp[i-w-1][j+k]+k*bp[i]);

dp[i][j]表示第i天拥有j个石头的最大价值。

其实每次求得都是最有策略,所有dp[i-w-1]表示的就是i-w-1以前的最优,故不同往前遍历。

那么主要需要优化的是:

对于买石头,容量为j时,维护从j-k到j的转移最大值。即从哪个容量转移过来能得到最大效益。

对于卖石头,容量为j时,维护从j+k到j的转移最大值。即从哪个容量转移过来能得到最大效益。

见代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define inf 10000010
#define Maxn 2010
#define Min(a,b) (a)>(b)?(b):(a)
using namespace std;
int dp[Maxn][Maxn],as[Maxn],bs[Maxn],ap[Maxn],bp[Maxn];
struct Que{
    int val,pos;
}que[10000];
int main()
{
    int n,t,p,w,i,j,k;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d%d",&n,&p,&w);
        for(i=1;i<=n;i++)
            for(j=0;j<=p;j++)
            dp[i][j]=-inf;//初始化
        for(i=1;i<=n;i++)
            scanf("%d%d%d%d",ap+i,bp+i,as+i,bs+i);
        for(i=1;i<=w+1;i++)//预处理
            for(j=0;j<=as[i];j++)
                dp[i][j]=-j*ap[i];
        for(i=2;i<=n;i++)
        {
            for(j=0;j<=p;j++)
            dp[i][j]=max(dp[i][j],dp[i-1][j]);//预处理
            if(i<=w+1) continue;
            int head=1,rear=0;
            for(j=0;j<=p;j++)//买石头
            {
                while(head<=rear&&(que[rear].val-(j-que[rear].pos)*ap[i])<=dp[i-w-1][j])
                    rear--;
                que[++rear].pos=j,que[rear].val=dp[i-w-1][j];
                if(que[head].pos<j-as[i]) head++;
                dp[i][j]=max(dp[i][j],que[head].val+(que[head].pos-j)*ap[i]);
            }
            head=1,rear=0;
            for(j=p;j>=0;j--)//卖石头
            {
                while(head<=rear&&(que[rear].val+(que[rear].pos-j)*bp[i])<=dp[i-w-1][j])
                    rear--;
                que[++rear].pos=j,que[rear].val=dp[i-w-1][j];
                if(que[head].pos>j+bs[i]) head++;
                dp[i][j]=max(dp[i][j],que[head].val+(que[head].pos-j)*bp[i]);
            }
        }
        int Max=0;
        for(i=0;i<=p;i++)//找出最大效益
            if(dp[n][i]>Max)
            Max=dp[n][i];
        printf("%d
",Max);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/wangfang20/p/3238245.html