hdu3041 单调队列优化dp

https://vjudge.net/solution/2611950 上师兄的代码。。
这个地方的维护的是单调递减的队列,,
这样

买进: f[i][j]=max(f[i-W-1][k]-(j-k)*e[i].ap,f[i][j])。在这里j-e[i].as

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<string>
#include<queue>
#include<cstring>
using namespace std;
#define sf scanf
#define pf printf
#define mem(a,b) memset(a,b,sizeof(a));
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define M 200020
#define mod 998244353
#define ULL unsigned long long
#define LL long long
#define inf 0x3f3f3f3f
#define ls (rt<<1)
#define rs (ls|1)
#define md ((ll+rr)>>1)
#define mxn  2020
//2017年08月09日08:09:06   10min

//2017年08月09日08:25:16  10min

int  dp[mxn][mxn];
int ap[mxn],bp[mxn],as[mxn],bs[mxn];
int t,P,w;
void read(){
    sf("%d%d%d",&t,&P,&w);
    rep(i,1,t)sf("%d%d%d%d",&ap[i],&bp[i],&as[i],&bs[i]);
    rep(i,0,t)rep(j,0,P)dp[i][j]=-inf;
}
int main(){
    freopen("in.txt","r",stdin);
    int T ;sf("%d",&T);
    while(T--){
        read();
        for(int i=1;i<=t;++i){
            for(int j=0;j<=P;++j)
                dp[i][j]=max(dp[i-1][j],dp[i][j]);
            if(i<=w+1){
                for(int j=0;j<=min(as[i],P);++j)
                    dp[i][j]=max(dp[i][j],-j*as[i]);
                continue;
            }
            int u=i-w-1;
            deque<int>q;
            for(int j=0;j<=P;++j){
                while(!q.empty()&&dp[u][q.back()]+q.back()*ap[i]<dp[u][j]+j*ap[i])q.pop_back();
                q.push_back(j);
                while(!q.empty()&&q.front()+as[i]<j)q.pop_front();
                if(!q.empty())
                    dp[i][j]=max(dp[i][j],dp[u][q.front()]-(j-q.front())*ap[i]);
            }
            while(!q.empty())q.pop_front();
            for(int j=P;j>=0;--j){
                while(!q.empty()&&dp[u][q.back()]+q.back()*bp[i]<dp[u][j]+j*bp[i])q.pop_back();
                q.push_back(j);
                while(!q.empty()&&q.front()-bs[i]>j)q.pop_front();
                if(!q.empty())
                    dp[i][j]=max(dp[i][j],dp[u][q.front()]+(q.front()-j)*bp[i]);
            }
        }
        int ans=0;
        rep(i,0,P)ans=max(ans,dp[t][i]);
        pf("%d\n",ans);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值