题目大意:容量可以为负的01背包
题解:每个挂钩体积改为1−ai,然后大力背包
体积为正的逆序枚举,为负的顺序枚举……根据01背包原理YY一下就知道了
我的收获:方便的负数下标重载技巧
#include <iostream>
#include <cstring>
#include <cstdio>
#include <climits>
#include <algorithm>
using namespace std;
#define INF LLONG_MAX/2
#define M 2020
#define ll long long
int n,w,v;
struct arr{
ll a[M<<1];
ll &operator[](int x){
if(x<-n) x=-n;if(x>n) x=n;
return a[x+2000];
}
}f;
void DP()
{
f[0]=0;
for(int i=1;i<=n;i++){
scanf("%d%d",&w,&v);w=-w+1;
if(w>=0) for(int j=n;j>=-n;j--) f[j+w]=max(f[j+w],f[j]+v);
else for(int j=-n;j<=n;j++) f[j+w]=max(f[j+w],f[j]+v);
}
}
void work(){
DP();
ll ret=0;for(int i=-n;i<=1;i++) ret=max(ret,f[i]);
cout<<ret<<endl;
}
void init()
{
cin>>n;
for(int i=-n;i<=n;i++) f[i]=-INF;
}
int main()
{
init();
work();
return 0;
}