题解:
单调队列优化DP
用f[i][j]表示第 i 天持有 j 股股票的最大收益
首先发现状态转移时 i 是不需要枚举的,一定从 i-w-1 天转移而来
然后对于买入和卖出分别建一个单调队列即可
//by sdfzchy
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
const int inf=(1<<30),N=2010;
int n,m;
inline int in()
{char ch=getchar();int f=1,tmp=0;while(ch<'0'||ch>'9') {
if(ch=='-') f=-1;ch=getchar();}while(ch>='0'&&ch<='9') {tmp=(tmp<<1)+(tmp<<3)+(ch-'0');ch=getchar();}return tmp*f;
}
int p,w;
int a[N],b[N],c[N],d[N];
int f[N][N];struct Q
{int pos,val;
}q[N];int main()
{int T=in();while(T--){memset(f,0xaf,sizeof(f)); f[0][0]=0;n=in(),p=in(),w=in();for(int i=1;i<=n;i++) a[i]=in(),b[i]=in(),c[i]=in(),d[i]=in();for(int i=1;i<=w+1;i++)for(int j=0;j<=c[i];j++)f[i][j]=-j*a[i];for(int i=1;i<=n;i++){if(i<=w+1){for(int j=0;j<=p;j++)f[i][j]=max(f[i][j],f[i-1][j]);continue;}int l=1,r=0;for(int j=0;j<=p;j++){f[i][j]=max(f[i-1][j],f[i][j]);int cur=f[i-w-1][j]+j*a[i];while(l<=r&&q[r].val<=cur) r--;q[++r]=(Q){j,cur};while(l<=r&&j-q[l].pos>c[i]) l++;f[i][j]=max(f[i][j],q[l].val-j*a[i]);}l=1,r=0;for(int j=p;j>=0;j--){int cur=f[i-w-1][j]+j*b[i];while(l<=r&&q[r].val<=cur) r--;q[++r]=(Q){j,cur};while(l<=r&&q[l].pos-j>d[i]) l++;f[i][j]=max(f[i][j],q[l].val-j*b[i]);}}printf("%d\n",f[n][0]);}return 0;
}