01背包(体积为负,改变区间) 之 poj 2184

//  [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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值