UVA - 10032 Tug of War (二进制标记+01背包)

Description

Problem F: Tug of War

A tug of war is to be arranged at the local office picnic. For the tug of war, the picnickers must be divided into two teams. Each person must be on one team or the other; the number of people on the two teams must not differ by more than 1; the total weight
of the people on each team should be as nearly equal as possible.

Input

The input begins with a single positive integer on a line by itself indicating the number of the cases following, each of them as described below. This line is followed by a blank line, and there is also a blank line between two consecutive inputs.

The first line of input contains n the number of people at the picnic.
n lines follow. The first line gives the weight of person 1; the second the weight of person 2; and so on. Each weight is an integer between 1 and 450. There are at most 100 people at the picnic.

Output

For each test case, the output must follow the description below. The outputs of two consecutive cases will be separated by a blank line.

Your output will be a single line containing 2 numbers: the total weight of the people on one team, and the total weight of the people on the other team. If these numbers differ, give the lesser first.

Sample Input

1

3
100
90
200

Sample Output

190 200

题意:求将人分为两部分,人数相差不超过1个,求重量差最小的可能

思路:二维的背包会超时,可能姿势不对,学了别人的二进制标记,dp[i]表示重量为i时的人数有几个,用<<几位表示

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
typedef long long ll;
using namespace std;
const int maxn = 45005;
const int inf = 0x3f3f3f3f;

ll dp[maxn];
int w[110];
int n, sum, mid;

int main() {
	int t;
	scanf("%d", &t);
	while (t--) {
		scanf("%d", &n);
		sum = 0;
		for (int i = 0; i < n; i++) {
			scanf("%d", &w[i]);
			sum += w[i];
		}
		mid = (n+1) >> 1;
		memset(dp, 0, sizeof(dp));
		dp[0] = 1;
		for (int i = 0; i < n; i++)
			for (int j = sum; j >= w[i]; j--)
				dp[j] |= dp[j-w[i]] << 1;
		int Min = 0, Max = inf;
		for (int i = 0; i <= sum; i++)
			for (int j = 0; j <= mid; j++)
				if (dp[i] & (1ll << j) && abs(2 * j - n) <= 1)
					if (abs(sum - 2 * i) < Max - Min) {
						Max = max(sum-i, i);
						Min = min(sum-i, i);
					}
		printf("%d %d\n", Min, Max);
		if (t)
			printf("\n");
	}
	return 0;
}

UVA - 10032 Tug of War (二进制标记+01背包),布布扣,bubuko.com

时间: 2024-12-30 06:39:11

UVA - 10032 Tug of War (二进制标记+01背包)的相关文章

UVa 10032 - Tug of War

题目:有n个人分成两组,两组人数差不能超过1,找到两组的人重量之差的最小值. 分析:dp,状态压缩01背包.zoj1880升级版. 首先,考虑二维背包. 因为必须放在两个组中的一组,直接背包所有可到状态,取出相差不超过 1的最接近 sum/2的值即可. 然后,优化. 如果直接利用二维背包,由于数据组数较多会TLE,这里利用状态压缩的一维背包: 状态:f(i)表示总重为i时的所有可能的人数,f(i)的值,的第k位上的数是1则代表有k人的组合方式. 转移:f(i)= f(i)| (f(i-w[j])

UVA 12563 Jin Ge Jin Qu hao 01背包变形

基本的01背包,更新的时候保持背包里每一个元素的num最大然后time尽量长 CSDN也支持makedown了试一下 12563 Jin Ge Jin Qu hao (If you smiled when you see the title, this problem is for you ^_^) For those who don't know KTV, see: http://en.wikipedia.org/wiki/Karaoke_box There is one very popul

UVA 562 Dividing coins 分硬币(01背包,简单变形)

题意:一袋硬币两人分,要么公平分,要么不公平,如果能公平分,输出0,否则输出分成两半的最小差距. 思路:将提供的整袋钱的总价取一半来进行01背包,如果能分出出来,就是最佳分法.否则背包容量为一半总价的包能装下的硬币总值就是其中一个人能分得的最多的钱了,总余下的钱减去这包硬币总值.(只需要稍微考虑一下总值是奇数/偶数的问题) 1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #includ

UVa 12563 Jin Ge Jin Qu hao(01背包)

题意  你在KTV还剩t秒钟的时间  你需要在n首歌中选择尽量多的歌使得歌的数量最多的前提下剩下的时间最小 至少要留一秒给劲歌金曲  所以是一个容量为t-1的01背包   d[i][j]表示恰用j秒时间在前i首歌中最多唱多少首  每个状态有两种选择 唱或不唱第i首歌 所以有转移方程d[i][j]=max(d[i-1][j],d[i-1][j-c[i]]+1) #include <bits/stdc++.h> using namespace std; const int N = 55, M =

UVA 12563 Jin Ge Jin Qu hao(01背包变形:两个背包内容)

题意: KTV里面有n首歌曲你可以选择,每首歌曲的时长都给出了. 对于每首歌曲,你最多只能唱1遍. 现在给你一个时间限制t (t<=10^9) , 问你在最多t-1秒的时间内可以唱多少首歌曲num , 且最长唱歌时间是多少time (time必须<=t-1) ? 最终输出num+1 和 time+678 即可. 注意: 你需要优先让歌曲数目最大的情况下,再去选择总时长最长的. //0 KB 39 ms #include<cstdio> #include<cstring>

lightoj-1147 - Tug of War(状压dp)

1147 - Tug of War PDF (English) Statistics ForumTime Limit: 4 second(s) Memory Limit: 32 MBA tug of war is to be arranged at the local office picnic. For the tug of war, the picnickers must be divided into two teams. Each person must be on one team o

UVA 562 Dividing coins --01背包的变形

01背包的变形. 先算出硬币面值的总和,然后此题变成求背包容量为V=sum/2时,能装的最多的硬币,然后将剩余的面值和它相减取一个绝对值就是最小的差值. 代码: #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; #define N 50007 int c[102],d

UVA 之11729 - Commando War

There is a war and it doesn't look very promising for your country. Now it's time to act. You have a commando squad at your disposal and planning an ambush on an important enemy camp located nearby. You have N soldiers in your squad. In your master-p

POJ 2576 Tug of War 随机算法

原题地址:http://poj.org/problem?id=2576 Tug of War Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 8525   Accepted: 2320 Description A tug of war is to be arranged at the local office picnic. For the tug of war, the picnickers must be divide