1. 程式人生 > >科大訊飛2018暑期實習招聘線上程式設計題:如何分糖果?

科大訊飛2018暑期實習招聘線上程式設計題:如何分糖果?

題目描述:小明和小紅是好朋友,但最近遇到一個棘手的問題,有一盒糖果要分成兩份但是每顆糖果質量都不盡相同,但為了分配的公平每份糖的糖果數量相差不得超過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;
}