单调队列优化dp
一题思维好题
就是有3个转移方程
$f_{i,j}=max(f_{i,j},f_{i-1,j})$ $(0\leq j\leq m)$
$f_{i,j}=max(f_{i,j},f_{i-w-1,k}+k*ap_i)-j*ap_i$ $(j-as_i\leq k<j)$
$f_{i,j}=max(f_{i,j},f_{i-w-1,k}+k*bp_i)-j*bp_i$ $(j<k\leq j+bs_i)$
初始化:$f_{i,j}=-ap_i*j $ $(0\leq j\leq as_i)$
容易观察到第二个和第三个可以用单调队列优化
于是就做完了
#include <bits/stdc++.h>
#define il inline
#define Max 2005
using namespace std;
il int read()
{
char c=getchar();
int x=0,f=1;
while(c>'9'||c<'0')
{
if(c=='-') f=-1;
c=getchar();
}
while(c>='0'&&c<='9')
{
x=x*10+c-'0';
c=getchar();
}
return x*f;
}
int n,m,w;
int f[Max][Max],ap,bp,as,bs,q[Max],ans;
int main()
{
memset(f,128,sizeof(f));
n=read(),m=read(),w=read();
for(int i=1;i<=n;i++)
{
ap=read(),bp=read(),as=read(),bs=read();
for(int j=0;j<=as;j++)
f[i][j]=-1*(j)*ap;
for(int j=0;j<=m;j++)
f[i][j]=max(f[i][j],f[i-1][j]);
if(i<=w) continue;
int l=1,r=0;
for(int j=0;j<=m;j++)
{
while(l<=r&&q[l]<j-as) l++;
while(l<=r&&f[i-w-1][q[r]]+q[r]*ap<=f[i-w-1][j]+j*ap) r--;
q[++r]=j;
if(l<=r) f[i][j]=max(f[i][j],f[i-w-1][q[l]]+q[l]*ap-j*ap);
}
l=1,r=0;
for(int j=m;j>=0;j--)
{
while(l<=r&&q[l]>j+bs) l++;
while(l<=r&&f[i-w-1][q[r]]+q[r]*bp<=f[i-w-1][j]+j*bp) r--;
q[++r]=j;
if(l<=r) f[i][j]=max(f[i][j],f[i-w-1][q[l]]+q[l]*bp-j*bp);
}
}
for(int i=0;i<=m;i++) ans=max(ans,f[n][i]);
cout<<ans<<endl;
}
最后一次更新于2021-09-28
0 条评论