因为有的钩子是可以不挂钩的,dp时需要注意 附上我自己的代码(思路类似01背包)
/*
可以发现,负数的挂饰是增加挂载点的工具,正数挂饰只有挂载点为0才需要考虑挂不挂的问题
先考虑用贪心去做,比如按照"代价/增加的挂钩数"排序,思考之后发现是不行的
就比如考虑要达到x个挂钩,要求最小化所选挂饰代价的总和,这很明显是一个经典的背包问题
那我们不妨考虑动态规划,然后发现n很小,可喜可贺可喜可贺(JOI是吧)
自己写代码时的两个错点
1、背包时注意是01不是完全背包
2、因为挂钩是可以不用的,所以37行加了个for(int j=n;j>=1;j--) f[j]=min(f[j],f[j+1]);
*/
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cstdio>
using namespace std;
int f[2005];
int a[2005],p;
bool cmp(int x,int y){
return x>y;
}
int main()
{
int n;cin>>n;
int t1,t2;
int s=1,ans=0;
memset(f,0x3f3f3f3f,sizeof(f));
f[0]=0;
for(int i=1;i<=n;i++){
cin>>t1>>t2;
if(t2>=0){
if(t1) {s+=t1-1;ans+=t2;}
else a[++p]=t2;
}
else{
t1--;
if(t1>=1) for(int j=n;j>=t1;j--) f[j]=min(f[j],f[j-t1]-t2);
for(int j=n;j>=1;j--) f[j]=min(f[j],f[j+1]);
}
}
sort(a+1,a+p+1,cmp);
t1=min(s,p);
for(int i=1;i<=t1;i++) ans+=a[i];
t1=0;
if(s<p){
a[s]=0;
for(int i=s+1;i<=p;i++){
a[i]+=a[i-1];
f[i-s]=a[i]-f[i-s];
t1=max(t1,f[i-s]);
}
}
ans+=t1;
cout<<ans<<endl;
return 0;
}