作者:11 | 来源:互联网 | 2023-08-10 19:28
题目描述:小明和小红是好朋友,但最近遇到一个棘手的问题,有一盒糖果要分成两份但是每颗糖果质量都不尽相同,但为了分配的公平每份糖的糖果数量相差不得超过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
#includeusing 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) }int main()
{int n;while (cin >> n) {vector sugers(n);int sum &#61; 0;for (int i &#61; 0; i > sugers[i];sum &#43;&#61; sugers[i];}int target &#61; sum / 2;int res &#61; 0, minchazhi &#61; INT_MAX;search(sugers, 0, 0, 0,res,target,minchazhi,sum,n);if(res>sum-res) cout <}