一道普通的单调队列优化动态规划
很容易得到动态规划方程:
[f[i][j] = max lbrace f[i-1][k] + a_i * j
brace
]
(f[i][j])为放入(i)个原料,当前锅里有(j)个原料
这算是个暴力吧,测评可得85
对于上式中的(k),其取值范围是在([j-1 , j+s-1])
所以我很不容易想到使用单调队列优化
在知道了这个数据结构的情况下,很容易就能做出这道题来
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define minn 5505
long long a[minn];
long long f[minn][minn]; //13107200
long long con[minn*2];
long long que[minn*2];
int main()
{
long long n,w,s;
long long maxn;
ios_base::sync_with_stdio(false);
cout.tie(NULL);
cin.tie(NULL);
cin>>n>>w>>s;
for(long long i=1;i<=n;i++)
cin>>a[i];
// for(int i=0;i<=n;i++)
// for(int j=0;j<=n;j++)
// f[i][j] = -1<<;
memset(f,0xcf,sizeof(f));
maxn=f[0][0];
f[0][0]=0;
for(long long i=1;i<=n;i++)
{
int lef=1,rig=0;
que[++rig] = f[i-1][w];
con[rig] = w;
for(int k=w ;k ;k--)
{
while(lef <= rig && con[lef] > k + s - 1 ) lef++;
while(lef <= rig && que[rig] < f[i-1][k-1]) rig--;
con[++rig] = k-1;
que[rig] = f[i-1][k-1];
f[i][k]= que[lef] + a[i] * k;
}
}
for(long long j=1;j<=w;j++)
maxn=max(f[n][j],maxn);
cout<<maxn;
}