POJ 2184 01背包 负数处理
题意
给你n
头奶牛,每头奶牛都有一个智商和情商,选出的若干头奶牛,使得智商和与情商和都大于等于0
的情况下,求智商总+
情商总和的最大值。
解决思路
这里是选和不选的问题,01
问题了。首先重量为正数时就是正常的01背包,但重量为负数时由于下标不能为负,我们需要增加数组长度。也就是把坐标0向正方向移动:0。。。offset。。。N
,0 - 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;
}