题目大意:给定一组成员,每个成员包含ts,tf两个值,两者都有负值,要你从这组成员中选出一些成员,保证ts的和不为负数,tf的和也不为负数,并且ts的和与tf的和最大。
解题思路:背包问题,把ts看做容量,tf看做价值,由于有负值,所以把最小负值平移到原点。
当ts为正数时,由于要利用到上次求到的结果,并且每个物品只能选一次,所以,按照从大到小扫描
当ts为负值时,从小到大扫描
#include
#include
#include
#include
using namespace std;
struct node
{
int ts, tf;
};
const int maxn = 110;
const int inf = 200000;
int n, ts, tf;
node cows[maxn];
int dp[inf + 10];
int main()
{
while(scanf("%d", &n) != EOF)
{
for(int i = 0; i <= inf; i++)
dp[i] = INT_MIN;
for(int i = 1; i <= n; i++)
{
scanf("%d %d", &cows[i].ts, &cows[i].tf);
}
dp[inf / 2] = 0;
for(int i = 1; i <= n ; i++)
{
if(cows[i].ts >= 0)
{
for(int j = inf; j >= cows[i].ts; j--)
{
if(dp[j - cows[i].ts] != INT_MIN)
dp[j] = max(dp[j], dp[j - cows[i].ts] + cows[i].tf);
}
}
else
{
for(int j = cows[i].ts; j <= inf + cows[i].ts; j++)
{
if(dp[j - cows[i].ts] != INT_MIN)
dp[j] = max(dp[j], dp[j - cows[i].ts] + cows[i].tf);
}
}
}
int ans = INT_MIN;
int val = inf / 2;
for(int i = val; i <= inf; i++)
{
if(dp[i] >= 0)
ans = max(ans, dp[i] + i - val);
}
printf("%d\n", ans);
}
return 0;
}