POJ 2184 01背包 负数处理

POJ 2184 01背包 负数处理

题意

给你n头奶牛,每头奶牛都有一个智商和情商,选出的若干头奶牛,使得智商和情商和都大于等于0的情况下,求智商总+情商总和的最大值。

解决思路

这里是选和不选的问题,01问题了。首先重量为正数时就是正常的01背包,但重量为负数时由于下标不能为负,我们需要增加数组长度。也就是把坐标0向正方向移动:0。。。offset。。。N0 - offset 之间为负数,offset - N之间为正数,dp[B]0。然后就可以进行01背包了。最后扫一遍正数区间更新一个最大值即可。

这里以智商为背包中的重量。

注意:开始我想给输入的数加上一个偏量不就行了嘛,但是这样不行,因为这样破坏了数据。

代码实现

//这里虽然题目给的数据是正负1000,但是还得大些才能过。
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<stack>
#include<queue>
#include<map>
typedef long long ll;
using namespace std;
const double esp = 1e-6;
const int inf = 0x3f3f3f3f;
const int MAXN = 2e5+7;
const int offset = 1e5;
const int rb = 2e5;
int sm[MAXN], f[MAXN], dp[MAXN];
int n;
int main()
{
	while(cin>>n)
	{
		for(int i=1; i<=n; i++){
			cin>>sm[i]>>f[i];
		}
		for(int i=0; i<=rb; i++)
			dp[i] = -inf;
		dp[offset] = 0;
		for(int i=1; i<=n; i++)
		{
			if(sm[i] >= 0)
				for(int j=rb; j>=sm[i]; j--)
					dp[j] = max(dp[j], dp[j-sm[i]] + f[i]);
			else 
				for(int j=0; j<=rb+sm[i]; j++)
					dp[j] = max(dp[j], dp[j-sm[i]] + f[i]);
		}
		int ans = 0;
		for(int i=offset; i<=rb; i++)
		{
			if(dp[i] >= 0)
				ans = max(ans, dp[i]+i-offset);
		}
		cout<<ans<<endl; 
	}
	return 0;
}

原文地址:https://www.cnblogs.com/alking1001/p/12368697.html