90分可能错的地方
查看原帖
90分可能错的地方
38031
星灵王楼主2024/7/31 16:58

因为有的钩子是可以不挂钩的,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;	
} 
2024/7/31 16:58
加载中...