两人分糖果问题

题目描述:小明和小红是好朋友,但最近遇到一个棘手的问题,有一盒糖果要分成两份但是每颗糖果质量都不尽相同,但为了分配的公平每份糖的糖果数量相差不得超过1,在此条件下两份糖果的质量差距尽可能小。

输入:一行数,包含一个数n,代表糖果数量,后面一次是n个整数一次表示每个糖果的质量,每个糖果的质量都是1到450之间的一个整数,每盒最多有20个糖果。

输出:每个样例输出两个数字分别为两堆糖果的质量,如不相同,先小后大。

样例

输入:5 9 6 5 8 7

输出:17 18
分析:
  1. 要求2人分得质量差距最小,则2人分得质量应该在所有糖果质量一半附近,且其中一人所得质量与总质量一半的差距应该是所有分配方法中最小的。
  2. 要求2人分得糖果数量相差不超过1,无论糖果总数n是奇数还是偶数,其中一人总会分得n/2个糖果。
思路:对每个糖果采用取或者不取的态度,随机从n个糖果中取得n/2个糖果,计算得到所有C(n,n/2)种分配方式,所得分配方式中与总质量一半相差最小的即为答案。

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int Min = INT_MAX;
int num;//糖果数量的一半,数量为奇数时,取下限。
int sum = 0;//所有糖果的质量
int res;

void devide(vector<int> candy, int w, int start, int cnt) {//w:目前已分得质量
	if (cnt == num) {//数量达到条件
		if (abs(w * 2 - sum) < Min) {//保存暂时最好结果
			res = w;
			Min = abs(w * 2 - sum);
		}
	}
	else {
		if (start == candy.size())return;//start从0开始,达到candy.size()说明已越界,结束递归。
		devide(candy, w, start + 1, cnt);//这颗糖果不取
		devide(candy, w + candy[start], start + 1, cnt + 1);//这颗糖果取。
	}
}
int main() {
	int n;
	cin >> n;
	vector<int> candy(n);
	for (int i = 0;i < n;i++) {
		cin >> candy[i];
		sum += candy[i];
	}
	num = n / 2;
	devide(candy, 0, 0, 0);
	if (res * 2 > sum) 
		cout << sum - res << " " << res << endl;
	else 
		cout << res << " " << sum - res << endl;
	return 0;
	

}

猜你喜欢

转载自blog.csdn.net/lccrun/article/details/80873722