http://poj.org/problem?id=2184
dp[s]表示当TS=s时,TF的最大值。
背包容量?——我们要找到它的最大值,不断分开累加正s和负s即可。
if (s > 0)
{
for (j = Max; j >= Min; --j)
dp[j + s] = max(dp[j + s], dp[j] + f);///dp[s]表示当TS=s时,TF的最大值
Max += s;
}
else
{
if (f <= 0) continue; ///剪枝
for (j = Min; j <= Max; ++j)
dp[j + s] = max(dp[j + s], dp[j] + f);///dp[s]表示当TS=s时,TF的最大值
Min += s;
}
完整代码:
/*32ms,1168KB*/
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int dp[200005];
int main()
{
int n, i, j, s, f, Min, Max;
memset(dp, -0x3f, sizeof(dp));
dp[Min = Max = 100000] = 0;
scanf("%d", &n);
for (i = 0; i < n; ++i)
{
scanf("%d%d", &s, &f);
if (s > 0)
{
for (j = Max; j >= Min; --j)
dp[j + s] = max(dp[j + s], dp[j] + f);///dp[s]表示当TS=s时,TF的最大值
Max += s;
}
else
{
if (f <= 0) continue; ///剪枝
for (j = Min; j <= Max; ++j)
dp[j + s] = max(dp[j + s], dp[j] + f);///dp[s]表示当TS=s时,TF的最大值
Min += s;
}
}
int ans = 0;
for (i = 100000; i <= Max; ++i)
if (dp[i] >= 0) ans = max(ans, dp[i] + (i - 100000));
printf("%d\n", ans);
return 0;
}