负值01背包

题意:n头牛,每头牛有一个幽默值和聪明值(有负数),问如何从中选择k头牛,使得幽默值和聪明值的和非负且最大。

思路:把问题看成01背包,背包的总容量为幽默值的和,每一头牛的幽默值和聪明值分别看成是物品的价值和体积。因为幽默值有可能为负数,不能做数组的下标,所以要先移位。

#include
#include
#include 
#include
#define inf 0x3f3f3f3f
using namespace std;
const int maxn=2e5+50;
const int shift=1000;
int n,f[maxn],s[maxn],dp[maxn],c,cnt[maxn],ans;
int main(){
	while(scanf("%d",&n)!=EOF){
		memset(f,0,sizeof(f));
		memset(s,0,sizeof(s));
		memset(dp,-inf,sizeof(dp));
		memset(cnt,0,sizeof(cnt));
		dp[0]=0;///除了 背包空间为0的时候最大价值为0外其他背包设置为理论上最小:-inf 
		c=0;
		for(int i=0;i=s[i];j--){
			if(dp[j]-cnt[j]*shift<=dp[j-s[i]]+f[i]-(cnt[j-s[i]]+1)*shift){///这里进行了移动预处理,所以要移回去 
				dp[j]=dp[j-s[i]]+f[i];
				cnt[j]=cnt[j-s[i]]+1;
			}
		}
		for(int i=0;i<=c;i++){
			if(i-shift*cnt[i]>=0&&dp[i]>=0){
				ans=max(ans,i-shift*cnt[i]+dp[i]);
			}
		}
		printf("%d\n",ans);
	}
	return 0;
} 

你可能感兴趣的:(dp)