// [7/21/2014 Sjm]/*题意:maximize the sum of TS and TF, but both of these values to be non-negative.解决思路:以 TS 作为体积,TF作为价值,在保证体积、价值非负的情况下,求解 sum,取其所有情况的最大值。难点:1)体积出现负数,将区间改变 [-100000, 100000] ---> [0, 200000]。 (注意此时始点 dp[100000], [0, 100000)表示 TS 为负,(100000, 200000]表示 TS 为正)2)状态转移时,对于 smartness 出现负数的处理 (二维更好理解一些,但是若写成一维,则注意内层循环的循环顺序(思想同“背包九讲”里的“优化空间”的方法))(在我看来:关键是对状态转移方程的理解程度,知道所求值是依赖谁求出来的,在一维数组中各个值的位置又在哪里)3)千万注意初始化,因为要保证“必须把背包装满”。。。
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int MAX = 200005;
const int INF = 0x3f3f3f3f;
int arr[105][2], dp[MAX];
int sum, N;
int Solve() {
memset(dp, -INF, sizeof(dp));
dp[100000] = 0;
for (int i = 1; i <= N; ++i) {
if (arr[i][0] > 0) {
for (int j = sum; j >= arr[i][0]; --j) { // 注意循环顺序,从大到小
if (dp[j - arr[i][0]] > -INF) {
dp[j] = max(dp[j], dp[j - arr[i][0]] + arr[i][1]);
}
}
}
else {
for (int j = 0; j <= sum + arr[i][0]; ++j) { // 注意循环次序,从小到大
if (dp[j - arr[i][0]] > -INF) {
dp[j] = max(dp[j], dp[j - arr[i][0]] + arr[i][1]);
}
}
}
}
int ans = 0;
// 由 TS 非负值的计算结果
for (int i = sum; i >= 100000; --i) {
if (dp[i] >= 0) { // 保证 TF 非负
ans = max(ans, dp[i] + i - 100000);
}
}
return ans;
}
int main()
{
//freopen("input.txt", "r", stdin);
scanf("%d", &N);
int sum1 = 0, sum2 = 0;
for (int i = 1; i <= N; ++i) {
scanf("%d %d", &arr[i][0], &arr[i][1]);
if (arr[i][0] > 0) {
sum += arr[i][0];
}
}
sum = sum + 100000; // TS 上界
printf("%d\n", Solve());
return 0;
}
// [7/21/2014 Sjm]/*题意:maximize the sum of TS and TF, but both of these values to be non-negative. 解决思路:以 TS 作为体积,TF作为价值,在保证体积、价值非负的情况下,求解 sum,取其所有情况的最大值。 难点:1)体积出现负数,将区间改变 [-100000, 100000]