题目描述:小明和小红是好朋友,但最近遇到一个棘手的问题,有一盒糖果要分成两份但是每颗糖果质量都不尽相同,但为了分配的公平每份糖的糖果数量相差不得超过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
#include
#include
#include
#include
using namespace std;
void search(const vector &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 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 <