【例题1】拔河比赛
【例题1】拔河比赛
题面
题目描述
在浙江师范大学 ACM 集训队,队员平时集训脑力劳动力比较重。为了劳逸结合,我们敬爱的韩老师准备了一场拔河比赛,让队员放松心情。
为了拔河比赛的公正性,韩老师提出以下要求:
\((1)\) 拔河比赛两边人数最多不能相差 \(1\)。
\((2)\) 每个队员都有体重,我们要使两边比赛的人体重和相差最小。
现在有 \(N\) 个队员,韩老师想你帮忙分配,并且把分配后两边体重和之差最小值输出。
输入格式
首先输入 \(T\),表示有 \(T\) 组样例。
每个样例:
首先输入人数 \(N\),占一行。
后面跟着 \(N\) 个数,表示 \(N\) 个人的体重 \(W_1...W_n\)。
输出格式
对于每个样例输出一行,一个整数表示两边体重之差的绝对值。
样例
样例输入
1
3
55 50 100
样例输出
5
数据范围与提示
对于 \(100\%\) 的数据,有 \(1\leq T \leq 50\),\(2\leq N\leq 20\),\(30\leq W_i \leq 120\)。
分析
- 可见题目的数据非常小
- 那么我们没必要想复杂,直接暴力搜索即可。
- 根据要求 \((1)\),我们可以知道人数始终有一方为 \(\lfloor \frac{n}{2} \rfloor\),另一方为 \(n-\lfloor \frac{n}{2} \rfloor\),也就是说我们需要将 \(n\) 对半选择。
- 如果我们选出了 \(y\) 个人,这 \(y\) 个人的体重和为 \(z\),\(n\) 个人的体重和为 \(S\),那么当 \(y = \lfloor \frac{n}{2} \rfloor\) 的时候体重差就是 \(abs(z - (S - z)) = abs(2\times z - S)\),这时候只需要对每一个体重差进行最小值比较即可。
Code
#include <bits/stdc++.h>
using namespace std;
const int N = 30;
int T, n, w[N], ans = 0x3f3f3f3f, s;
void dfs(int x, int y, int z) {
if (y == (n >> 1)) {
ans = min(ans, abs(2 * z - s));
return;
}
if (x > n)
return;
dfs(x + 1, y + 1, z + w[x]);
dfs(x + 1, y, z);
}
int main(void) {
cin >> T;
while (T--) {
cin >> n;
memset(w, 0, sizeof(w));
s = 0;
for (int i = 1; i <= n; ++i) cin >> w[i], s += w[i];
ans = 0x3f3f3f3f;
dfs(1, 0, 0);
cout << ans << endl;
}
return 0;
}