如何分糖果?

原题来源于科大讯飞的一道在线编程题

作者:知足常乐_健康第一
链接:https://www.nowcoder.com/discuss/76153
来源:牛客网

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

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

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

样例

输入:5 9 6 5 8 7

输出:17 18


一开始做这道题的时候,我纠结于“找到一个策略,按照这个策略分糖果就能得到结果”。但后来我发现,其实根本不需要找出这么个策略,只需用暴力搜索算法即可。关键点是:“每份糖的糖果数量相差不得超过1”,假设糖果数目是n,则分成的两堆糖果的数量一定是n/2和n-n/2。这就归结为一个组合问题:“如何在n个糖果中选n/2个糖果,使得选出的糖果堆和剩下的糖果堆质量之差最小?”

因此,只要搜索所有C(n,n/2)种分糖方法,就能找出差值最小的那种。

这里重点解释下search函数:

第一个参数sugers,表示所有糖的质量。

第二个参数weight,表示当搜索到这一步时,已经选取出来的糖果的质量总和。

第三个参数start,表示“决定要不要选”的那颗糖果在sugers中的编号。

第四个参数count,我手里这堆糖果中糖果的数量。如果count到达了n/2,表明搜索到一种分法,可以进行比较了。

第五个参数res,表示“当前搜索过的所有分法中最好的分法”,当搜索完后,就是结果。

第六个参数target,是糖果的总重量/2。

第七个参数minchazhi,表示“当前搜索过的所有分法中最好的分法与target的差值”,是分法好坏的依据。

最后两个,sum是糖果的总重量,n是糖果的总数。

#include<iostream>
#include<vector>
#include<algorithm>
#include<math.h>
#include<limits.h>

using namespace std;

void search(const vector<int> &sugers, int weight, int start, int count, int &res,int target,int& minchazhi,int sum,int n)
{
    //用搜索法
    //我自己在糖果堆中选糖果,对于每一颗糖果,我可以选或者不选
    //如果选,count+1,表示我当前手里的糖果的数量
    //每次选完,我手里的糖果达到总数量的一半后,就进行手里糖果重量与总质量一半的最小差值minchazhi的更新
    //并记录在当前最小差值下的我手里糖果的质量,最后的res就是结果
	if (count == n/2) {
		if (abs(2 * weight - sum) < minchazhi) {
            //这次搜索的结果比上次更好,用res记录这个更好的结果
			res = weight;
			minchazhi = abs(2 * weight - sum);
		}
	}
	else {
		if (start < sugers.size()) {
            //还可以继续搜索
			search(sugers,weight, start + 1, count, res, target, minchazhi, sum,n);
			search(sugers, weight+sugers[start], start + 1, count+1, res, target, minchazhi, sum,n);
		}
	}
}


int main()
{
	int n;
	while (cin >> n) {
	    vector<int> sugers(n);
	    int sum = 0;
	    for (int i = 0; i < n; i++) {
		cin >> sugers[i];
		sum += sugers[i];
	    }
	    int target = sum / 2;
	    int res = 0, minchazhi = INT_MAX;
	    search(sugers, 0, 0, 0,res,target,minchazhi,sum,n);
        if(res>sum-res) cout <<sum-res << ' ' << res << endl;
        else cout <<res << ' ' << sum-res << endl;
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_26286193/article/details/80298083
今日推荐