POJ2576 Tug of War 二维背包

题目大意

一群人拔河,给出每个人的重量,要求两队人数之差不超过1人,且每队总重量之差最小。

思路

选出严格总人数一半(或+1)的人为一队,在该队重量不超过所有人总重量一半的情况下,使其重量最大。

人数一维,最终结果严格为其最大限制:总人数一半;队总重量一维,最终结果尽量大,不一定为其最大限制:所有人总重量一半。

所以初始化时,应将DP数组初始化为-∞,循环结束时,在DP[totV]中求最大值。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cstdarg>
using namespace std;

const int MAX_W = 23000, MAX_V = 55, MAX_ORG = 110;

int _max(int a, int b)
{
	return b == 0 ? a : max(a, b);
}

int Dp(int totV, int totObj, int totW, int *objW)
{
	static int DP[MAX_W][MAX_V];
	memset(DP, 0xcf, sizeof(DP));
	DP[0][0] = 0;
	for (int obj = 1; obj <= totObj; obj++)
		for (int w = totW; w >= objW[obj]; w--)
			for (int v = totV; v >= 1; v--)
				DP[w][v] = _max(DP[w][v], DP[w - objW[obj]][v - 1] + objW[obj]);
	int ans = 0;
	for (int i = 0; i <= totW; i++)
		ans = max(ans, DP[i][totV]);
	return ans;
}

int main()
{
#ifdef _DEBUG
	freopen("c:\noi\source\input.txt", "r", stdin);
#endif
	int n, sum = 0, ws[MAX_ORG];
	memset(ws, 0, sizeof(ws));
	scanf("%d", &n);
	for (int i = 1; i <= n; i++)
	{
		scanf("%d", i + ws);
		sum += ws[i];
	}
	int lighter = Dp(n / 2, n, (sum + 1) / 2, ws);
	if ((n / 2) * 2 != n)
		lighter = max(lighter, Dp(n / 2 + 1, n, (sum + 1) / 2, ws));
	int weighter = sum - lighter;
	if (lighter > weighter)
		swap(lighter, weighter);
	printf("%d %d
", lighter, weighter);
	return 0;
}

  

原文地址:https://www.cnblogs.com/headboy2002/p/8502900.html