您的位置:首页 > 其它

POJ 2184 Cow Exhibition

2015-12-01 12:52 323 查看
01背包问题的变种。不过需要注意的是有两个技巧

1. 将坐标轴整体右横移,这样的话就不存在负权值了,原来的零点变为现在的区间中点。

2. 正权值即为正常的01背包,从大大小,但当负权值时,需要从小到大。不知道该如何严格证明,但是自己找个例子实践一下的话会发现是对的,这样的话本轮计算用到的值恰好是上轮的结果。

#include <iostream>
#include <cstdio>

using namespace std;

const int MAXN = 105;
const int MAXV = 2 * 1e5 + 5;
const int INF = 0x3f3f3f3f;

int dp[MAXV], s[MAXN], f[MAXN], n;

inline int max(int a, int b)
{
return a > b ? a : b;
}

int main()
{
int mid = 1e5;
while (scanf("%d", &n) != EOF)
{
for (int i = 0; i < n; i++)
scanf("%d%d", &s[i], &f[i]);

for (int i = 0; i < MAXV; i++)
dp[i] = -INF;

dp[mid] = 0;

for (int i = 0; i < n; i++)
{
if (s[i] > 0)
{
for (int j = MAXV; j >= s[i]; j--)
dp[j] = max(dp[j], dp[j - s[i]] + f[i]);
}
else
{
for (int j = 0; j < MAXV + s[i]; j++)
dp[j] = max(dp[j], dp[j - s[i]] + f[i]);
}
}

int ans = 0;

for (int i = 1e5; i <= 2 * 1e5; i++)
if (dp[i] >= 0 && dp[i] + i - 1e5 > ans)
ans = dp[i] + i - 1e5;

printf("%d\n", ans);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: