P5858

一道普通的单调队列优化动态规划

很容易得到动态规划方程:

\[f[i][j] = max \lbrace f[i-1][k] + a_i * j \rbrace \]

\(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;
}

posted @ 2020-08-21 21:15  ·Iris  阅读(773)  评论(0)    收藏  举报