bzoj 4247: 挂饰【dp】

bzoj上访问负下标会跑到奇怪的地方……
其实可以滚动数组优化,但是我看能过就懒得改了
设f[i][j]为已经算了前i个挂饰,当前有j个空的钩子,转移就是f[i][j]=max(f[i-1][j],f[i-1][max(min(j-a[i]+1,n),-n)]+b[i])
注意到只有-n<=j<=n的范围内j是有用的,所以时空都是n^2的,负的j算的时候直接+n即可

#include<iostream>
#include<cstdio>
using namespace std;
const int N=4005;
int n,a[N],b[N],f[N][N],ans;
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
		scanf("%d%d",&a[i],&b[i]);
	for(int i=2;i<=n;i++)
		f[0][i+n]=-2e9;
	for(int i=1;i<=n;i++)
		for(int j=-n;j<=n;j++)
			f[i][j+n]=max(f[i-1][j+n],f[i-1][max(min(j-a[i]+1,n),-n)+n]+b[i]);
	for(int i=0;i<=n;i++)
		ans=max(ans,f[n][i+n]);
	printf("%d
",ans);
	return 0;
}
原文地址:https://www.cnblogs.com/lokiii/p/9636829.html