题意:存在n头牛,每头牛有情商和智商,都可为负数,在情商之和和智商之和都不为负数的情况下求怎样选择能使得情商与智商之和总和最大。存在负数的01背包。
题解:将智商当作背包容量,另一个为价值,但是背包容量不能为负,所以要将智商每一个加上1000。看起来简单,但是处理起来还是有很多地方需要注意的。
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<stack>
#include<vector>
#include<map>
#include<set>
#include<cstdlib>
#include<string>
#define INF 0x3f3f3f3f
#define MAXM 200000 + 10
#define MAXN 100 + 10
using namespace std;
typedef long long ll;
int n;
struct node{
int s, f;
}no[MAXN];
struct DP{
int ans;
int num;
}dp[MAXM];
void init()
{
memset(no, 0, sizeof(no));
memset(dp, 0, sizeof(dp));
for(int i = 1; i < MAXM; i ++)
dp[i].ans = -INF;
}
int main()
{
scanf("%d", &n);
init();
int maxs = 0;
for(int i = 0; i < n; i ++){
int s, f; scanf("%d %d", &s, &f);
no[i].s = s + 1000, no[i].f = f;
maxs += no[i].s;
}
for(int i = 0; i < n; i ++){
for(int j = maxs; j >= no[i].s; j --){
//这里判断的地方非常重要,不然就会wa了
if(dp[j].ans - dp[j].num * 1000 < dp[j-no[i].s].ans + no[i].f - (dp[j-no[i].s].num + 1) * 1000){
dp[j].ans = dp[j-no[i].s].ans + no[i].f;
dp[j].num = dp[j-no[i].s].num + 1;
}
}
}
int ans = 0;
for(int i = maxs; i >= 0; i --){
if(i - (dp[i].num * 1000) >= 0 && dp[i].ans >= 0)
ans = max(ans, dp[i].ans + (i - dp[i].num * 1000));
}
printf("%d\n", ans);
}
/*
The WAM is F**KING interesting .
*/