美文网首页
任意数分三组,使得每组的和尽量相等

任意数分三组,使得每组的和尽量相等

作者: IT孤独者 | 来源:发表于2017-01-03 22:52 被阅读0次

题目:任意数分三组,使得每组的和尽量相等
思路:第一次遇到这个题目的时候,那叫一个难字,对于算法题,算法本身可能并没有什么,但是如何获得求解算法的思路是一个关键。对于本题,我们可以采用归纳总结的方法。比如,任意数组分成一组,使得每组的和尽量相等。任意的数组分成两组,使得每组的和尽量相等。从这两个基本的问题,我们容易知道,如果数组总和整除分组数的商就是分组后的和(如果可以实现的话,多数情况是接近),当然还有一个极端的情况,比如数组中的最大值,大于这个商,这时候,我们可以使用降纬的方法,把其中一个分组的值设置成这个最大值,对于剩下的值采用同样的思路。(这个使用反证法很容易证明的)

代码如下:

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

typedef vector<int> vec_int;
typedef vector<vector<int> > vec_vec_int;

void Output(int nNum)
{
    cout << nNum  << " ";
}

void Output2(const vec_int & vecNum)
{
    for_each(vecNum.begin(), vecNum.end(), Output);
    cout << endl;
}

void CalZu(vec_vec_int & vecZu, int nZu, const vec_int & vecNum, int nBegin)
{
    if (vecNum.size() <= nBegin) return;

    int nSum = 0;
    int nAvg = 0;
    for (int i=nBegin; i<vecNum.size(); ++i) 
        nSum += vecNum[i];

    nAvg = nSum / nZu;
    if (nSum % nZu != 0)
        nAvg += 1;

    if (nAvg < vecNum[nBegin]) {
        vecZu[nZu-1].push_back(vecNum[nBegin]);
        CalZu(vecZu, nZu-1, vecNum, nBegin+1);
    } else {
        vec_int vecSum(nZu, nAvg);
        for (int i=nBegin; i<vecNum.size(); ++i) {
            int k = 0;
            int nTmpMin = vecSum[k] - vecNum[i];
            for (int j=1; j<vecSum.size(); ++j) {
                int nTmp = vecSum[j] - vecNum[i];
                if ((nTmpMin < 0 && nTmp >=  0)
                    || (nTmpMin < 0 && nTmpMin < nTmp)
                    || (nTmp > 0 && nTmpMin > nTmp) ) {
                    nTmpMin = nTmp;
                    k = j;
                }
            }
            vecZu[k].push_back(vecNum[i]);
            vecSum[k] -= vecNum[i];
        }
    }
}

int main(int argc, char ** argv)
{
    int a[] = {9, 8, 6, 6, 6, 5, 6, 5};
    // int a[] = {1003, 1002, 103, 102, 101, 3, 2, 1};
    int aLen = sizeof(a) / sizeof(int);

    vec_int vecNum(a, a+aLen);

    sort(vecNum.begin(), vecNum.end(), greater<int>());

    cout << "Input:" << endl;
    for_each(vecNum.begin(), vecNum.end(), Output); 
    cout << endl;

    const int nZu = 3;

    vec_vec_int vecZu(nZu);

    CalZu(vecZu, nZu, vecNum, 0);

    cout << "Output:" << endl;
    for_each(vecZu.begin(), vecZu.end(), Output2);
}

相关文章

网友评论

      本文标题:任意数分三组,使得每组的和尽量相等

      本文链接:https://www.haomeiwen.com/subject/sbdnvttx.html